aboutsummaryrefslogtreecommitdiffstats
path: root/branches/gpgme-0-3-branch/gpgmeplug
diff options
context:
space:
mode:
Diffstat (limited to 'branches/gpgme-0-3-branch/gpgmeplug')
-rw-r--r--branches/gpgme-0-3-branch/gpgmeplug/ChangeLog189
-rw-r--r--branches/gpgme-0-3-branch/gpgmeplug/Makefile.am39
-rw-r--r--branches/gpgme-0-3-branch/gpgmeplug/cryptplug.h1906
-rw-r--r--branches/gpgme-0-3-branch/gpgmeplug/gpgme-openpgp.c60
-rw-r--r--branches/gpgme-0-3-branch/gpgmeplug/gpgme-smime.c60
-rw-r--r--branches/gpgme-0-3-branch/gpgmeplug/gpgmeplug.c2863
-rw-r--r--branches/gpgme-0-3-branch/gpgmeplug/gpgmeplug.dox121
7 files changed, 5238 insertions, 0 deletions
diff --git a/branches/gpgme-0-3-branch/gpgmeplug/ChangeLog b/branches/gpgme-0-3-branch/gpgmeplug/ChangeLog
new file mode 100644
index 00000000..dd359c39
--- /dev/null
+++ b/branches/gpgme-0-3-branch/gpgmeplug/ChangeLog
@@ -0,0 +1,189 @@
+2002-09-20 Werner Koch <[email protected]>
+
+ * gpgmeplug.c (nextCertificate): Sanity check for empty tmp_dn.
+
+2002-08-20 Steffen Hansen <[email protected]>
+
+ * Use gpgme_op_import_ext() instead of gpgme_op_import(). We
+ should now be able to better check for the case when we have no
+ error, but still no certificate was imported.
+
+2002-07-31 Steffen Hansen <[email protected]>
+
+ * Renamed importCertificate() to importCertificateWithFPR() and
+ implemented importCertificateFromMem().
+
+2002-07-03 Werner Koch <[email protected]>
+
+ * gpgmeplug.c (nextCertificate): Actually free the entire array
+ and don't loop over tmp_dn and double free the first item.
+ Spotted by Bernhard Herzog.
+
+2002-07-01 Werner Koch <[email protected]>
+
+ * gpgmeplug.c (findCertificates): Reintroduced a free which must
+ have been removed after my last fix. This avoids a memory leak
+ when a fingerprint was not found. Removed the double loop
+ increment in the code to release the arrays.
+ (make_fingerprint): Removed superfluous check on retrun value of
+ xmalloc.
+ (safe_free): Removed. Changed all callers to use a regular free
+ and at appropriate palces set the free pointer to NULL. That
+ safe_free stuff seems to have been copied verbatim from some
+ Mutt example code I posted.
+ (storeNewCharPtr): Use xmalloc instead of an unchecked
+ malloc. Removed superfluous string termination.
+ (parseAddress): Use xmalloc instead of an unchecked malloc.
+ (nextAddress): Ditto.
+ (xstrdup): Oops, obviously I calculated the length wrong when
+ coded this. Tsss, wrote xstrdup some hundreds times but missed it
+ this time. Thanks to Steffen Hansen for noticing it.
+
+ * gpgmeplug.c: Moved a few helper functions more to the top.
+ Fixed comment syntax. Merged a copyright notice somewhere in the
+ middle of the file with the one at the top.
+
+2002-06-28 Werner Koch <[email protected]>
+
+ * gpgmeplug.c (xmalloc): New.
+ (safe_malloc): Removed this macro and replaced it at all places
+ without return values checks by xmalloc.
+ (xstrdup): New. Replaces funny named macro with different
+ semantics. Changed all callers to the new semantic.
+ (findCertificates): Don't free duplicate free the FPR array
+ values. Removed the unneeded initialization. Replaces the
+ gcc-ish use dynamic allocation of automatic variables by repalce
+ maxCerts with a macro MAXCERTS. Made some comments Real C (tm).
+ (startListCertificates): Removed uneeded cast from xmalloc.
+
+2002-06-28 Bernhard Reiter <[email protected]>
+
+ * gpgmeplug.c: new macro days_to_seconds().
+ this also fixes the dividing factor.
+ (signatureCertificateDaysLeftToExpiry)
+ (preceiverCertificateDaysLeftToExpiry): using the new macro
+
+ (caCertificateDaysLeftToExpiry)
+ (rootCertificateDaysLeftToExpiry): using new macro in deactivated code.
+
+
+2002-06-27 Steffen Hansen <[email protected]>
+
+ * gpgmeplug.c: Fixed pattern related bug.
+
+ * cryptplug.h, gpgmeplug.c: Handle truncated data from dirmngr.
+
+2002-06-25 Steffen Hansen <[email protected]>
+
+ * cryptplug.h, gpgmeplug.c: New function importCertificate() for importing a
+ certificate from the temp. db to the real one given a fingerprint.
+
+2002-06-20 Werner Koch <[email protected]>
+
+ * gpgmeplug.c (reorder_dn): Added missing stdpart list terminator.
+
+2002-05-30 Steffen Hansen <[email protected]>
+
+ * cryptplug.h, gpgmeplug.c: Added certificate info listing functions.
+ Not yet complete.
+ Converted more C99 style comments to "classic" style.
+
+2002-03-23 Werner Koch <[email protected]>
+
+ * gpgmeplug.c: Converted it to real C; i.e. use standard comments -
+ we are doing ISO C 90. Translated a few German remarks and
+ commented on some things.
+
+2002-03-08 Steffen Hansen <[email protected]>
+
+ * A little better address-parsing. Not real rfc822 yet, but at
+ least it fetches the address between '<' and '>' now if they are
+ present.
+
+2002-03-07 Steffen Hansen <[email protected]>
+
+ * gpgmeplug.c (encryptMessage): Made the function accept multiple
+ reciepients via addressee -- it is now parsed af a comma-separated
+ list.
+
+2002-03-06 Werner Koch <[email protected]>
+
+ * gpgmeplug.c (signMessage): Fixed offbyone. Don't include the
+ EOS character into the signature.
+ (checkMessageSignature): Ditto.
+
+2002-02-28 Kalle Dalheimer <[email protected]>
+
+ * gpgmeplug.c (signMessage): Implemented warning when signature
+ certificates are about to expire
+ (isEmailInCertificate): Added support for checking whether the
+ signer's email address is contained in his certificate.
+
+ * cryptplug.h: Implemented warning when signature
+ certificates are about to expire
+
+2002-02-27 Marcus Brinkmann <[email protected]>
+
+ * gpgmeplug.c (signMessage): Fix code syntax.
+
+2002-02-01 Marcus Brinkmann <[email protected]>
+
+ * Makefile.am (EXTRA_gpgme_openpgp_la_SOURCES): New variable.
+ (EXTRA_gpgme_smime_la_SOURCES): Likewise.
+
+ * gpgmeplug.c (passphrase_cb): Fix type of third argument.
+
+2002-01-16 Marcus Brinkmann <[email protected]>
+
+ * gpgme-openpgp.c: New file.
+ * Makefile.am (gpgme_openpgp_la_SOURCES): Replace gpgmeplug.c with
+ gpgme-openpgp.c.
+
+2002-01-15 Marcus Brinkmann <[email protected]>
+
+ * gpgmeplug.c: Renamed to ...
+ * gpgme-openpgp.c: ... this. New file.
+ * gpgsmplug.c: Renamed to ...
+ * gpgme-smime.c: ... this. new file.
+ * Makefile.am: Rewritten to use libtool's module functionality.
+
+2001-12-19 Marcus Brinkmann <[email protected]>
+
+ * Makefile.am (lib_LTLIBRARIES): Rename to ...
+ (noinst_LTLIBRARIES): ... this target.
+
+2001-12-19 Marcus Brinkmann <[email protected]>
+
+ * Makefile.am (libgpgmeplug_la_SOURCES): Remove gpgme.h.
+ (libgpgsmplug_la_SOURCES): Likewise.
+
+2001-11-29 Marcus Brinkmann <[email protected]>
+
+ * gpgmeplug.c (checkMessageSignature): Add call to gpgme_set_protocol.
+
+2001-11-24 Marcus Brinkmann <[email protected]>
+
+ * Makefile.am (libgpgsmplug_la_SOURCES): Fix source file.
+
+2001-11-22 Marcus Brinkmann <[email protected]>
+
+ * Makefile.am (libgpgsmplug_la_LIBADD): New variable.
+ (libgpgsmplug_la_LDFLAGS): Likewise.
+ (libgpgsmplug_la_SOURCES): Likewise.
+ (lib_LTLIBRARIES): Add libgpgsmplug.la.
+ (INCLUDES): Include the local gpgme.h.
+
+ * gpgmeplug.c (signMessage): Set protocol.
+ (GPGMEPLUG_PROTOCOL) [!GPGMEPLUG_PROTOCOL]: Set
+ GPGMEPLUG_PROTOCOL.
+ * gpgsmplug.c: New file.
+
+2001-11-21 Marcus Brinkmann <[email protected]>
+
+ * gpgmeplug.c: Include config.h only if [HAVE_CONFIG_H]. Do not
+ include util.h.
+ (deinitialize): Use free, not _gpgme_free.
+ (setDirectoryServers): Use calloc, not xtrycalloc. Use free, not
+ _gpgme_free. Use malloc instead xtrymalloc.
+ (appendDirectoryServer): Use realloc, not xtryrealloc.
+
diff --git a/branches/gpgme-0-3-branch/gpgmeplug/Makefile.am b/branches/gpgme-0-3-branch/gpgmeplug/Makefile.am
new file mode 100644
index 00000000..78422a03
--- /dev/null
+++ b/branches/gpgme-0-3-branch/gpgmeplug/Makefile.am
@@ -0,0 +1,39 @@
+# $Id$
+#
+# Makefile.am - Automake specification file for GPGMEPLUG.
+# GPGMEPLUG is a GPGME based cryptography plug-in
+# following the common CRYPTPLUG specification.
+#
+# Copyright (C) 2001 by Klar?lvdalens Datakonsult AB
+# Copyright (C) 2002 g10 Code GmbH
+#
+# GPGMEPLUG is free software; you can redistribute it and/or modify
+# it under the terms of GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# GPGMEPLUG is distributed in the hope that it will be useful,
+# it under the terms of GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+#
+## Process this file with automake to produce Makefile.in
+
+INCLUDES = -I$(top_srcdir)/gpgme
+
+pkglib_LTLIBRARIES = gpgme-openpgp.la gpgme-smime.la
+
+gpgme_openpgp_la_SOURCES = cryptplug.h gpgme-openpgp.c
+EXTRA_gpgme_openpgp_la_SOURCES = gpgmeplug.c
+gpgme_openpgp_la_LIBADD = ../gpgme/libgpgme.la
+gpgme_openpgp_la_LDFLAGS = -module -avoid-version
+
+gpgme_smime_la_SOURCES = cryptplug.h gpgme-smime.c
+EXTRA_gpgme_smime_la_SOURCES = gpgmeplug.c
+gpgme_smime_la_LIBADD = ../gpgme/libgpgme.la
+gpgme_smime_la_LDFLAGS = -module -avoid-version
diff --git a/branches/gpgme-0-3-branch/gpgmeplug/cryptplug.h b/branches/gpgme-0-3-branch/gpgmeplug/cryptplug.h
new file mode 100644
index 00000000..325a62a9
--- /dev/null
+++ b/branches/gpgme-0-3-branch/gpgmeplug/cryptplug.h
@@ -0,0 +1,1906 @@
+/* -*- Mode: C -*-
+
+ $Id$
+
+ CRYPTPLUG - an independent cryptography plug-in API
+
+ Copyright (C) 2001 by Klar�lvdalens Datakonsult AB
+
+ CRYPTPLUG is free software; you can redistribute it and/or modify
+ it under the terms of GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ CRYPTPLUG is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+*/
+
+#ifndef CRYPTPLUG_H
+#define CRYPTPLUG_H
+
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#else
+typedef char bool;
+#define true 1
+#define false 0
+#endif
+
+/*! \file cryptplug.h
+ \brief Common API header for CRYPTPLUG.
+
+ CRYPTPLUG is an independent cryptography plug-in API
+ developed for Sphinx-enabeling KMail and Mutt.
+
+ CRYPTPLUG was designed for the Aegypten project, but it may
+ be used by 3rd party developers as well to design pluggable
+ crypto backends for the above mentioned MUAs.
+
+ \note All string parameters appearing in this API are to be
+ interpreted as UTF-8 encoded.
+
+ \see pgpplugin.c
+ \see gpgplugin.c
+*/
+
+/*! \defgroup groupGeneral Loading and Unloading the Plugin, General Functionality
+
+ The functions in this section are used for loading and
+ unloading plugins. Note that the actual locating of the plugin
+ and the loading and unloading of the dynamic library is not
+ covered here; this is MUA-specific code for which support code
+ might already exist in the programming environments.
+*/
+
+/*! \defgroup groupDisplay Graphical Display Functionality
+
+ The functions in this section return stationery that the
+ MUAs can use in order to display security functionality
+ graphically. This can be toolbar icons, shortcuts, tooltips,
+ etc. Not all MUAs will use all this functionality.
+*/
+
+/*! \defgroup groupConfig Configuration Support
+
+ The functions in this section provide the necessary
+ functionality to configure the security functionality as well
+ as to query configuration settings. Since all configuration
+ settings will not be saved with the plugin, but rather with
+ the MUA, there are also functions to set configuration
+ settings programmatically; these will be used on startup of
+ the plugin when the MUA transfers the configuration values it
+ has read into the plugin. Usually, the functions to query and
+ set the configuration values are not needed for anything but
+ saving to and restoring from configuration files.
+*/
+
+
+/*! \defgroup groupConfigSign Signature Configuration
+ \ingroup groupConfig
+
+ The functions in this section provide the functionality
+ to configure signature handling and set and query the
+ signature configuration.
+*/
+
+/*! \defgroup groupConfigCrypt Encryption Configuration
+ \ingroup groupConfig
+
+ The functions in this section provide the functionality
+ to configure encryption handling and set and query the
+ encryption configuration.
+
+ \note Whenever the term <b> encryption</b> is used here,
+ it is supposed to mean both encryption and decryption,
+ unless otherwise specified.
+*/
+
+/*! \defgroup groupConfigDir Directory Service Configuration
+ \ingroup groupConfig
+
+ This section contains messages for configuring the
+ directory service.
+*/
+
+
+/*! \defgroup groupCertHand Certificate Handling
+
+ The following methods are used to maintain and query certificates.
+*/
+
+
+/*! \defgroup groupSignCryptAct Signing and Encrypting Actions
+
+ This section describes methods and structures
+ used for signing and/or encrypting your mails.
+*/
+
+
+/*! \defgroup groupSignAct Signature Actions
+ \ingroup groupSignCryptAct
+
+ This section describes methods that are used for working
+ with signatures.
+*/
+
+/*! \defgroup groupCryptAct Encryption and Decryption
+ \ingroup groupSignCryptAct
+
+ The following methods are used to encrypt and decrypt
+ email messages.
+*/
+
+/*! \defgroup groupCertAct Certificate Handling Actions
+
+ The functions in this section provide local certificate management.
+*/
+
+/*! \defgroup groupCRLAct CRL Handling Actions
+
+ This section describes functions for managing CRLs.
+*/
+
+/*! \defgroup groupAdUsoInterno Important functions to be used by plugin implementors ONLY.
+
+ This section describes functions that have to be used by
+ plugin implementors but should not be used by plugin users
+ directly.
+
+ If you are not planning to write your own cryptography
+ plugin <b>you should ignore this</b> section!
+*/
+
+/*! \defgroup certList Certificate Info listing functions
+ */
+
+
+typedef enum {
+ Feature_undef = 0,
+
+ Feature_SignMessages = 1,
+ Feature_VerifySignatures = 2,
+ Feature_EncryptMessages = 3,
+ Feature_DecryptMessages = 4,
+ Feature_SendCertificates = 5,
+ Feature_WarnSignCertificateExpiry = 6,
+ Feature_WarnSignEmailNotInCertificate = 7,
+ Feature_PinEntrySettings = 8,
+ Feature_StoreMessagesWithSigs = 9,
+ Feature_EncryptionCRLs = 10,
+ Feature_WarnEncryptCertificateExpiry = 11,
+ Feature_WarnEncryptEmailNotInCertificate = 12,
+ Feature_StoreMessagesEncrypted = 13,
+ Feature_CheckCertificatePath = 14,
+ Feature_CertificateDirectoryService = 15,
+ Feature_CRLDirectoryService = 16,
+ Feature_CertificateInfo = 17
+} Feature;
+
+/* dummy values */
+typedef enum {
+ PinRequest_undef = 0,
+
+ PinRequest_Always = 1,
+ PinRequest_WhenAddingCerts = 2,
+ PinRequest_AlwaysWhenSigning = 3,
+ PinRequest_OncePerSession = 4,
+ PinRequest_AfterMinutes = 5
+} PinRequests;
+
+
+typedef enum {
+ SignatureCompoundMode_undef = 0,
+
+ SignatureCompoundMode_Opaque = 1,
+ SignatureCompoundMode_Detached = 2
+} SignatureCompoundMode;
+
+
+typedef enum {
+ SendCert_undef = 0,
+
+ SendCert_DontSend = 1,
+ SendCert_SendOwn = 2,
+ SendCert_SendChainWithoutRoot = 3,
+ SendCert_SendChainWithRoot = 4
+} SendCertificates;
+
+
+typedef enum {
+ SignAlg_undef = 0,
+
+ SignAlg_SHA1 = 1
+} SignatureAlgorithm;
+
+
+
+typedef enum {
+ EncryptAlg_undef = 0,
+
+ EncryptAlg_RSA = 1,
+ EncryptAlg_SHA1 = 2,
+ EncryptAlg_TripleDES = 3
+} EncryptionAlgorithm;
+
+typedef enum {
+ SignEmail_undef = 0,
+
+ SignEmail_SignAll = 1,
+ SignEmail_Ask = 2,
+ SignEmail_DontSign = 3
+} SignEmail;
+
+typedef enum {
+ EncryptEmail_undef = 0,
+
+ EncryptEmail_EncryptAll = 1,
+ EncryptEmail_Ask = 2,
+ EncryptEmail_DontEncrypt = 3
+} EncryptEmail;
+
+typedef enum {
+ CertSrc_undef = 0,
+
+ CertSrc_Server = 1,
+ CertSrc_Local = 2,
+ CertSrc_ServerLocal = CertSrc_Server | CertSrc_Local
+} CertificateSource;
+
+
+/*! \ingroup groupSignAct
+ \brief Flags used to compose the SigStatusFlags value.
+
+ This status flags are used to compose the SigStatusFlags value
+ returned in \c SignatureMetaDataExtendedInfo after trying to
+ verify a signed message part's signature status.
+
+ The normal flags may <b>not</b> be used together with the
+ special SigStat_NUMERICAL_CODE flag. When finding the special
+ SigStat_NUMERICAL_CODE flag in a SigStatusFlags value you
+ can obtain the respective error code number by substracting
+ the SigStatusFlags value by SigStat_NUMERICAL_CODE: this is
+ used to transport special status information NOT matching
+ any of the normal predefined status codes.
+
+ \note to PlugIn developers: Implementations of the CryptPlug API
+ should try to express their signature states by bit-wise OR'ing
+ the normal SigStatusFlags values. Using the SigStat_NUMERICAL_CODE
+ flag should only be used as for exceptional situations where no
+ other flag(s) could be used. By using the normal status flags your
+ PlugIn's users will be told an understandable description of the
+ status - when using (SigStat_NUMERICAL_CODE + internalCode) they
+ will only be shown the respective code number and have to look
+ into your PlugIn's manual to learn about it's meaning...
+*/
+enum {
+ SigStat_VALID = 0x0001, /* The signature is fully valid */
+ SigStat_GREEN = 0x0002, /* The signature is good. */
+ SigStat_RED = 0x0004, /* The signature is bad. */
+ SigStat_KEY_REVOKED = 0x0010, /* One key has been revoked. */
+ SigStat_KEY_EXPIRED = 0x0020, /* One key has expired. */
+ SigStat_SIG_EXPIRED = 0x0040, /* The signature has expired. */
+ SigStat_KEY_MISSING = 0x0080, /* Can't verify: key missing. */
+ SigStat_CRL_MISSING = 0x0100, /* CRL not available. */
+ SigStat_CRL_TOO_OLD = 0x0200, /* Available CRL is too old. */
+ SigStat_BAD_POLICY = 0x0400, /* A policy was not met. */
+ SigStat_SYS_ERROR = 0x0800, /* A system error occured. */
+
+ SigStat_NUMERICAL_CODE = 0x8000 /* An other error occured. */
+};
+typedef unsigned long SigStatusFlags;
+
+
+#define CRYPTPLUG_CERT_DOES_NEVER_EXPIRE 365000
+
+
+
+
+/*! \ingroup groupGeneral
+ \brief This function returns the version string of this cryptography
+ plug-in.
+
+ If the plugins initialization fails the calling process might want
+ to display the library version number to the user for checking if
+ there is an old version of the library installed...
+
+ \note This function <b>must</b> be implemented by each plug-in using
+ this API specification.
+*/
+const char* libVersion( void );
+
+/*! \ingroup groupGeneral
+ \brief This function returns a URL to be used for reporting a bug that
+ you found (or suspect, resp.) in this cryptography plug-in.
+
+ If the plugins for some reason cannot specify an appropriate URL you
+ should at least be provided with a text giving you some advise on
+ how to report a bug.
+
+ \note This function <b>must</b> be implemented by each plug-in using
+ this API specification.
+*/
+const char* bugURL( void );
+
+/*! \ingroup groupGeneral
+ \brief This function sets up all internal structures.
+
+ Plugins that need no initialization should provide an empty
+ implementation. The method returns \c true if the initialization was
+ successful and \c false otherwise. Before this function is called,
+ no other plugin functions should be called; the behavior is
+ undefined in this case.
+
+ \note This function <b>must</b> be implemented by each plug-in using
+ this API specification.
+*/
+bool initialize( void );
+
+/*! \ingroup groupGeneral
+ \brief This function frees all internal structures.
+
+ Plugins that do not keep any internal structures should provide an
+ empty implementation. After this function has been called,
+ no other plugin functions should be called; the behavior is
+ undefined in this case.
+
+ \note This function <b>must</b> be implemented by each plug-in using
+ this API specification.
+*/
+void deinitialize( void );
+
+/*! \ingroup groupGeneral
+ \brief This function returns \c true if the
+ specified feature is available in the plugin, and
+ \c false otherwise.
+
+ Not all plugins will support all features; a complete Sphinx
+ implementation will support all features contained in the enum,
+ however.
+
+ \note This function <b>must</b> be implemented by each plug-in using
+ this API specification.
+*/
+bool hasFeature( Feature );
+
+
+/*! \ingroup groupDisplay
+ \brief Returns stationery to indicate unsafe emails.
+*/
+void unsafeStationery( void** pixmap, const char** menutext, char* accel,
+ const char** tooltip, const char** statusbartext );
+
+/*! \ingroup groupDisplay
+ \brief Returns stationery to indicate signed emails.
+*/
+void signedStationery( void** pixmap, const char** menutext, char* accel,
+ const char** tooltip, const char** statusbartext );
+
+/*! \ingroup groupDisplay
+ \brief Returns stationery to indicate encrypted emails.
+*/
+void encryptedStationery( void** pixmap, const char**
+ menutext, char* accel,
+ const char** tooltip, const char** statusbartext );
+
+/*! \ingroup groupDisplay
+ \brief Returns stationery to indicate signed and encrypted emails.
+*/
+void signedEncryptedStationery( void** pixmap, const char**
+ menutext, char* accel,
+ const char** tooltip, const char** statusbartext );
+
+/*! \ingroup groupConfigSign
+ \brief This function returns an XML representation of a
+ configuration dialog for configuring signature
+ handling.
+
+ The syntax is that of <filename>.ui</filename>
+ files as specified in the <emphasis>Imhotep</emphasis>
+ documentation. This function does not execute or show the
+ dialog in any way; this is up to the MUA. Also, what the
+ MUA makes of the information provided highly depends on
+ the MUA itself. A GUI-based MUA will probably create a
+ dialog window (possibly integrated into an existing
+ configuration dialog in the application), while a
+ terminal-based MUA might generate a series of questions or
+ a terminal based menu selection.
+*/
+const char* signatureConfigurationDialog( void );
+
+/*! \ingroup groupConfigSign
+ \brief This function returns an XML representation of a
+ configuration dialog for selecting a signature key.
+
+ This will typically be used when the user wants to select a
+ signature key for one specific message only; the defaults
+ are set in the dialog returned by
+ signatureConfigurationDialog().
+*/
+const char* signatureKeySelectionDialog( void );
+
+/*! \ingroup groupConfigSign
+ \brief This function returns an XML representation of a
+ configuration dialog for selecting a signature
+ algorithm.
+
+ This will typically be used when the user wants
+ to select a signature algorithm for one specific message only; the
+ defaults are set in the dialog returned by
+ signatureConfigurationDialog().
+*/
+const char* signatureAlgorithmDialog( void );
+
+/*! \ingroup groupConfigSign
+ \brief This function returns an XML representation of a
+ configuration dialog for selecting whether an email
+ message and its attachments should be sent with or
+ without signatures.
+
+ This will typically be used when the
+ user wants to select a signature key for one specific
+ message only; the defaults are set in the dialog returned
+ by signatureConfigurationDialog().
+*/
+const char* signatureHandlingDialog( void );
+
+/*! \ingroup groupConfigSign
+ \brief Sets the signature key certificate that identifies the
+ role of the signer.
+*/
+void setSignatureKeyCertificate( const char* certificate );
+
+/*! \ingroup groupConfigSign
+ \brief Returns the signature key certificate that identifies
+ the role of the signer.
+*/
+const char* signatureKeyCertificate( void );
+
+/*! \ingroup groupConfigSign
+ \brief Sets the algorithm used for signing.
+*/
+void setSignatureAlgorithm( SignatureAlgorithm );
+
+/*! \ingroup groupConfigSign
+ \brief Returns the algorithm used for signing.
+*/
+SignatureAlgorithm signatureAlgorithm( void );
+
+/*! \ingroup groupConfigSign
+\brief Sets whether signatures and signed data should be send
+ as opaque signed or
+ as multipart/signed message parts.
+*/
+void setSignatureCompoundMode( SignatureCompoundMode );
+
+/*! \ingroup groupConfigSign
+\brief Returns whether signatures and signed data will be send
+ as opaque signed or
+ as multipart/signed message parts.
+*/
+SignatureCompoundMode signatureCompoundMode( void );
+
+/*! \ingroup groupConfigSign
+ \brief Sets which certificates should be sent with the
+ message.
+*/
+void setSendCertificates( SendCertificates );
+/*! \ingroup groupConfigSign
+ \brief Returns which certificates should be sent with the
+ message.
+*/
+SendCertificates sendCertificates( void );
+
+/*! \ingroup groupConfigSign
+ \brief Specifies whether email should be automatically
+ signed, signed after confirmation, signed after
+ confirmation for each part or not signed at all.
+*/
+void setSignEmail( SignEmail );
+
+/*! \ingroup groupConfigSign
+ \brief Returns whether email should be automatically
+ signed, signed after confirmation, signed after
+ confirmation for each part or not signed at all.
+*/
+SignEmail signEmail( void );
+
+
+/*! \ingroup groupConfigSign
+ \brief Specifies whether a warning should be emitted when the user
+ tries to send an email message unsigned.
+*/
+void setWarnSendUnsigned( bool );
+
+
+/*! \ingroup groupConfigSign
+ \brief Returns whether a warning should be emitted when the user
+ tries to send an email message unsigned.
+*/
+bool warnSendUnsigned( void );
+
+
+/*! \ingroup groupConfigSign
+ \brief Specifies whether sent email messages should be stored
+ with or without their signatures.
+*/
+void setSaveSentSignatures( bool );
+
+/*! \ingroup groupConfigSign
+ \brief Returns whether sent email messages should be stored
+ with or without their signatures.
+*/
+bool saveSentSignatures( void );
+
+/*! \ingroup groupConfigSign
+ \brief Specifies whether a warning should be emitted if the
+ email address of the sender is not contained in the
+ certificate.
+*/
+void setWarnNoCertificate( bool );
+
+/*! \ingroup groupConfigSign
+ \brief Returns whether a warning should be emitted if the
+ email address of the sender is not contained in the
+ certificate.
+*/
+bool warnNoCertificate( void );
+
+/*!
+ \ingroup groupConfigSign
+ \brief Returns true if the specified email address is contained
+ in the specified certificate.
+*/
+bool isEmailInCertificate( const char* email, const char* certificate );
+
+/*! \ingroup groupConfigSign
+ \brief Specifies how often the PIN is requested when
+ accessing the secret signature key.
+*/
+void setNumPINRequests( PinRequests );
+
+/*! \ingroup groupConfigSign
+ \brief Returns how often the PIN is requested when
+ accessing the secret signature key.
+*/
+PinRequests numPINRequests( void );
+
+/*! \ingroup groupConfigSign
+ \brief Specifies the interval in minutes the PIN must be reentered if
+ numPINRequests() is PinRequest_AfterMinutes.
+*/
+void setNumPINRequestsInterval( int );
+
+
+/*! \ingroup groupConfigSign
+ \brief Returns the interval in minutes the PIN must be reentered if
+ numPINRequests() is PinRequest_AfterMinutes.
+*/
+int numPINRequestsInterval( void );
+
+
+/*! \ingroup groupConfigSign
+ \brief Specifies whether the certificate path should be
+ followed to the root certificate or whether locally stored
+ certificates may be used.
+*/
+void setCheckSignatureCertificatePathToRoot( bool );
+
+/*! \ingroup groupConfigSign
+ \brief Returns whether the certificate path should be
+ followed to the root certificate or whether locally stored
+ certificates may be used.
+*/
+bool checkSignatureCertificatePathToRoot( void );
+
+/*! \ingroup groupConfigSign
+ \brief Specifies whether certificate revocation lists should
+ be used.
+*/
+void setSignatureUseCRLs( bool );
+
+/*! \ingroup groupConfigSign
+ \brief Returns whether certificate revocation lists should
+ be used.
+*/
+bool signatureUseCRLs( void );
+
+/*! \ingroup groupConfigSign
+ \brief Specifies whether a warning should be emitted if the
+ signature certificate expires in the near future.
+*/
+void setSignatureCertificateExpiryNearWarning( bool );
+
+/*! \ingroup groupConfigSign
+ \brief Returns whether a warning should be emitted if
+ the signature certificate expires in the near future.
+*/
+bool signatureCertificateExpiryNearWarning( void );
+
+/*! \ingroup groupConfigSign
+ \brief Returns the number of days that are left until the
+ specified certificate expires.
+
+ Negative values show how many days ago the certificate DID expire,
+ a zero value means the certificate expires today,
+ special value CRYPTPLUG_CERT_DOES_NEVER_EXPIRE means there is
+ no expire date stored in this certificate.
+
+ \param certificate the certificate to check
+*/
+int signatureCertificateDaysLeftToExpiry( const char* certificate );
+
+/*! \ingroup groupConfigSign
+ \brief Specifies the number of days which a signature certificate must
+ be valid before it is considered to expire in the near
+ future.
+*/
+void setSignatureCertificateExpiryNearInterval( int );
+
+/*! \ingroup groupConfigSign
+ \brief Returns the number of days which a signature certificate must
+ be valid before it is considered to expire in the near
+ future.
+*/
+int signatureCertificateExpiryNearInterval( void );
+
+/*! \ingroup groupConfigSign
+ \brief Specifies whether a warning should be emitted if the
+ CA certificate expires in the near future.
+*/
+void setCACertificateExpiryNearWarning( bool );
+
+/*! \ingroup groupConfigSign
+ \brief Returns whether a warning should be emitted if
+ the CA certificate expires in the near future.
+*/
+bool caCertificateExpiryNearWarning( void );
+
+/*! \ingroup groupConfigSign
+ \brief Returns the number of days that are left until the
+ CA certificate of the specified certificate expires.
+
+ Negative values show how many days ago the certificate DID expire,
+ a zero value means the certificate expires today,
+ special value CRYPTPLUG_CERT_DOES_NEVER_EXPIRE means there is
+ no expire date stored in this certificate.
+
+ \param certificate the certificate to check
+*/
+int caCertificateDaysLeftToExpiry( const char* certificate );
+
+/*! \ingroup groupConfigSign
+ \brief Specifies the number of days which a CA certificate must
+ be valid before it is considered to expire in the near
+ future.
+*/
+void setCACertificateExpiryNearInterval( int );
+
+/*! \ingroup groupConfigSign
+ \brief Returns the number of days which a CA certificate must
+ be valid before it is considered to expire in the near
+ future.
+*/
+int caCertificateExpiryNearInterval( void );
+
+/*! \ingroup groupConfigSign
+ \brief Specifies whether a warning should be emitted if the
+ root certificate expires in the near future.
+*/
+void setRootCertificateExpiryNearWarning( bool );
+
+/*! \ingroup groupConfigSign
+ \brief Returns whether a warning should be emitted if
+ the root certificate expires in the near future.
+*/
+bool rootCertificateExpiryNearWarning( void );
+
+/*! \ingroup groupConfigSign
+ \brief Returns the number of days that are left until the
+ root certificate of the specified certificate expires.
+
+ Negative values show how many days ago the certificate DID expire,
+ a zero value means the certificate expires today,
+ special value CRYPTPLUG_CERT_DOES_NEVER_EXPIRE means there is
+ no expire date stored in this certificate.
+
+ \param certificate the certificate to check
+*/
+int rootCertificateDaysLeftToExpiry( const char* certificate );
+
+/*! \ingroup groupConfigSign
+ \brief Specifies the number of days which a root certificate must
+ be valid before it is considered to expire in the near
+ future.
+*/
+void setRootCertificateExpiryNearInterval( int );
+
+/*! \ingroup groupConfigSign
+ \brief Returns the number of days which a signature certificate must
+ be valid before it is considered to expire in the near
+ future.
+*/
+int rootCertificateExpiryNearInterval( void );
+
+
+
+
+/*! \ingroup groupConfigCrypt
+ \brief This function returns an XML representation of a
+ configuration dialog for configuring encryption
+ handling.
+
+ The syntax is that of <filename>.ui</filename>
+ files as specified in the <emphasis>Imhotep</emphasis>
+ documentation. This function does not execute or show the
+ dialog in any way; this is up to the MUA. Also, what the
+ MUA makes of the information provided highly depends on
+ the MUA itself. A GUI-based MUA will probably create a
+ dialog window (possibly integrated into an existing
+ configuration dialog in the application), while a
+ terminal-based MUA might generate a series of questions or
+ a terminal based menu selection.
+*/
+const char* encryptionConfigurationDialog( void );
+
+/*! \ingroup groupConfigCrypt
+ \brief This function returns an XML representation of a
+ configuration dialog for selecting an encryption
+ algorithm.
+
+ This will typically be used when the user wants
+ to select an encryption algorithm for one specific message only; the
+ defaults are set in the dialog returned by
+ encryptionConfigurationDialog().
+*/
+const char* encryptionAlgorithmDialog( void );
+
+/*! \ingroup groupConfigCrypt
+ \brief This function returns an XML representation of a
+ configuration dialog for selecting whether an email
+ message and its attachments should be encrypted.
+
+ This will typically be used when the
+ user wants to select an encryption key for one specific
+ message only; the defaults are set in the dialog returned
+ by encryptionConfigurationDialog().
+*/
+const char* encryptionHandlingDialog( void );
+
+/*! \ingroup groupConfigCrypt
+ \brief This function returns an XML representation of a
+ dialog that lets the user select the certificate to use
+ for encrypting.
+
+ If it was not possible to determine the
+ correct certificate from the information in the email
+ message, the user is presented with a list of possible
+ certificates to choose from. If a unique certificate was
+ found, this is presented to the user, who needs to confirm
+ the selection of the certificate. This procedure is repeated
+ for each recipient of the email message.
+*/
+const char* encryptionReceiverDialog( void );
+
+/*! \ingroup groupConfigCrypt
+ \brief Sets the algorithm used for encrypting.
+*/
+void setEncryptionAlgorithm( EncryptionAlgorithm );
+
+/*! \ingroup groupConfigCrypt
+ \brief Returns the algorithm used for encrypting.
+*/
+EncryptionAlgorithm encryptionAlgorithm( void );
+
+/*! \ingroup groupConfigCrypt
+ \brief Specifies whether email should be automatically
+ encrypted, encrypted after confirmation, encrypted after
+ confirmation for each part or not encrypted at all.
+*/
+void setEncryptEmail( EncryptEmail );
+
+/*! \ingroup groupConfigCrypt
+ \brief Returns whether email should be automatically
+ encrypted, encrypted after confirmation, encrypted after
+ confirmation for each part or not encrypted at all.
+*/
+EncryptEmail encryptEmail( void );
+
+/*! \ingroup groupConfigSign
+ \brief Specifies whether a warning should be emitted when the user
+ tries to send an email message unencrypted.
+*/
+void setWarnSendUnencrypted( bool );
+
+
+/*! \ingroup groupConfigSign
+ \brief Returns whether a warning should be emitted when the user
+ tries to send an email message unencrypted.
+*/
+bool warnSendUnencrypted( void );
+
+
+/*! \ingroup groupConfigCrypt
+ \brief Specifies whether encrypted email messages should be
+ stored encrypted or decrypted.
+*/
+void setSaveMessagesEncrypted( bool );
+
+/*! \ingroup groupConfigCrypt
+ \brief Returns whether encrypted email messages should be stored
+ encrypted or decrypted.
+*/
+bool saveMessagesEncrypted( void );
+
+
+/*! \ingroup groupConfigCrypt
+ \brief Specifies whether the certificate path should be checked
+ during encryption.
+*/
+void setCheckCertificatePath( bool );
+
+/*! \ingroup groupConfigCrypt
+ \brief Returns whether the certificate path should be checked
+ during encryption.
+*/
+bool checkCertificatePath( void );
+
+
+/*! \ingroup groupConfigCrypt
+ \brief Specifies whether the certificate path should be
+ followed to the root certificate or whether locally stored
+ certificates may be used.
+*/
+void setCheckEncryptionCertificatePathToRoot( bool );
+
+/*! \ingroup groupConfigCrypt
+ \brief Returns whether the certificate path should be
+ followed to the root certificate or whether locally stored
+ certificates may be used.
+*/
+bool checkEncryptionCertificatePathToRoot( void );
+
+
+/*! \ingroup groupConfigCrypt
+ \brief Specifies whether a warning should be emitted if the
+ certificate of the receiver expires in the near future.
+*/
+void setReceiverCertificateExpiryNearWarning( bool );
+
+/*! \ingroup groupConfigCrypt
+ \brief Returns whether a warning should be emitted if the
+ certificate of the receiver expires in the near future.
+*/
+bool receiverCertificateExpiryNearWarning( void );
+
+
+/*! \ingroup groupConfigCrypt
+ \brief Returns the number of days until the specified receiver
+ certificate expires.
+
+ Negative values show how many days ago the certificate DID expire,
+ a zero value means the certificate expires today,
+ special value CRYPTPLUG_CERT_DOES_NEVER_EXPIRE means there is
+ no expire date stored in this certificate.
+*/
+int receiverCertificateDaysLeftToExpiry( const char* certificate );
+
+
+
+/*! \ingroup groupConfigCrypt
+ \brief Specifies the number of days which a receiver certificate
+ must be valid before it is considered to expire in the near future.
+*/
+void setReceiverCertificateExpiryNearWarningInterval( int );
+
+/*! \ingroup groupConfigCrypt
+ \brief Returns the number of days which a receiver certificate
+ must be valid before it is considered to expire in the near future.
+*/
+int receiverCertificateExpiryNearWarningInterval( void );
+
+/*! \ingroup groupConfigCrypt
+ \brief Specifies whether a warning should be emitted if
+ a certificate in the chain expires in the near future.
+*/
+void setCertificateInChainExpiryNearWarning( bool );
+
+
+/*! \ingroup groupConfigCrypt
+ \brief Returns whether a warning should be emitted if a
+ certificate in the chain expires in the near future.
+*/
+bool certificateInChainExpiryNearWarning( void );
+
+
+
+/*! \ingroup groupConfigCrypt
+ \brief Specifies the number of days which a certificate in the chain
+ must be valid before it is considered to expire in the near future.
+*/
+void setCertificateInChainExpiryNearWarningInterval( int );
+
+/*! \ingroup groupConfigCrypt
+ \brief Returns the number of days which a certificate in the chain
+ must be valid before it is considered to expire in the near future.
+*/
+int certificateInChainExpiryNearWarningInterval( void );
+
+
+/*! \ingroup groupConfigCrypt
+ \brief Returns the number of days until the first certificate in
+ the chain of the receiver certificate expires.
+
+ Negative values show how many days ago the certificate DID expire,
+ a zero value means the certificate expires today,
+ special value CRYPTPLUG_CERT_DOES_NEVER_EXPIRE means there is
+ no expire date stored in this certificate.
+*/
+int certificateInChainDaysLeftToExpiry( const char* certificate );
+
+
+/*! \ingroup groupConfigCrypt
+ \brief Specifies whether a warning is emitted if the email address
+ of the receiver does not appear in the certificate.
+*/
+void setReceiverEmailAddressNotInCertificateWarning( bool );
+
+/*! \ingroup groupConfigCrypt
+ \brief Returns whether a warning is emitted if the email address
+ of the receiver does not appear in the certificate.
+*/
+bool receiverEmailAddressNotInCertificateWarning( void );
+
+
+/*! \ingroup groupConfigCrypt
+ \brief Specifies whether certificate revocation lists should
+ be used.
+*/
+void setEncryptionUseCRLs( bool );
+
+/*! \ingroup groupConfigCrypt
+ \brief Returns whether certificate revocation lists should
+ be used.
+*/
+bool encryptionUseCRLs( void );
+
+/*! \ingroup groupConfigCrypt
+ \brief Specifies whether a warning should be emitted if any
+ of the certificates involved in the signing process
+ expires in the near future.
+*/
+void setEncryptionCRLExpiryNearWarning( bool );
+
+/*! \ingroup groupConfigCrypt
+ \brief Returns whether a warning should be emitted if any
+ of the certificates involved in the signing process
+ expires in the near future.
+*/
+bool encryptionCRLExpiryNearWarning( void );
+
+/*! \ingroup groupConfigCrypt
+ \brief Specifies the number of days which a certificate must
+ be valid before it is considered to expire in the near
+ future.
+*/
+void setEncryptionCRLNearExpiryInterval( int );
+
+/*! \ingroup groupConfigCrypt
+ \brief Returns the number of days which a certificate must
+ be valid before it is considered to expire in the near
+ future.
+*/
+int encryptionCRLNearExpiryInterval( void );
+
+
+/*! \ingroup groupConfigCrypt
+ \brief Returns the number of days the currently active certification
+ list is still valid.
+*/
+int encryptionCRLsDaysLeftToExpiry( void );
+
+
+
+/*! \ingroup groupConfigDir
+ \brief This function returns an XML representation of a
+ configuration dialog for selecting a directory
+ server.
+*/
+const char* directoryServiceConfigurationDialog( void );
+
+/*! \ingroup groupConfigDir
+ \brief Lets you configure how certificates and certificate
+ revocation lists are retrieved (both locally and from directory
+ services).
+
+ Will mainly be used for restoring
+ configuration data; interactive configuration will be done
+ via the configuration dialog returned by
+ \c directoryServiceConfigurationDialog().
+*/
+void appendDirectoryServer( const char* servername, int port,
+ const char* description );
+
+
+
+
+/*! \ingroup groupConfigDir
+*/
+struct DirectoryServer {
+ char* servername;
+ int port;
+ char* description;
+};
+
+
+/*! \ingroup groupConfigDir
+ \brief Specifies a list of directory servers.
+
+ Will mainly be used for restoring
+ configuration data; interactive configuration will be done
+ via the configuration dialog returned by
+ \c directoryServiceConfigurationDialog().
+*/
+void setDirectoryServers( struct DirectoryServer[], unsigned int size );
+
+/*! \ingroup groupConfigDir
+ \brief Returns the list of directory servers.
+
+ Will mainly be used for saving configuration data; interactive
+ configuration will be done via the configuration dialog
+ returned by
+ \c directoryServiceConfigurationDialog().
+*/
+struct DirectoryServer* directoryServers( int* numServers );
+
+/*! \ingroup groupConfigDir
+ \brief Specifies whether certificates should be retrieved
+ from a directory server, only locally, or both.
+*/
+void setCertificateSource( CertificateSource );
+
+/*! \ingroup groupConfigDir
+ \brief Returns whether certificates should be retrieved
+ from a directory server, only locally, or both.
+*/
+CertificateSource certificateSource( void );
+
+/*! \ingroup groupConfigDir
+ \brief Specifies whether certificates should be retrieved
+ from a directory server, only locally, or both.
+*/
+void setCRLSource( CertificateSource );
+
+/*! \ingroup groupConfigDir
+ \brief Returns whether certificates should be retrieved
+ from a directory server, only locally, or both.
+*/
+CertificateSource crlSource( void );
+
+
+/*! \ingroup groupCertHand
+ \brief Returns \c true if and only if the
+ certificates in the certificate chain starting at
+ \c certificate are valid.
+
+ If \c level is non-null, the parameter contains
+ the degree of trust on a backend-specific scale. In an X.509
+ implementation, this will either be \c 1
+ (valid up to the root certificate) or \c 0
+ (not valid up to the root certificate).
+*/
+bool certificateValidity( const char* certificate, int* level );
+
+
+/*! \ingroup groupSignCryptAct
+ \brief Information record returned by signing and by encrypting
+ functions - this record should be used together with a
+ corresponding \c free_StructuringInfo() function call.
+
+ Use this information to compose a MIME object containing signed
+ and/or encrypted content (or to build a text frame around your
+ flat non-MIME message body, resp.)
+
+ <b>If</b> value returned in \c makeMimeObject is <b>TRUE</b> the
+ text strings returned in \c contentTypeMain and \c contentDispMain
+ and \c contentTEncMain (and, if required, \c content[..]Version and
+ \c bodyTextVersion and \c content[..]Sig) should be used to compose
+ a respective MIME object.<br>
+ If <b>FALSE</b> the texts returned in \c flatTextPrefix and
+ \c flatTextSeparator and \c flatTextPostfix are to be used instead.<br>
+ Allways <b>either</b> the \c content[..] and \c bodyTextVersion
+ parameters <b>or</b> the \c flatText[..] parameters are holding
+ valid data - never both of them may be used simultaneously
+ as plugins will just ignore the parameters not matching their
+ \c makeMimeObject setting.
+
+ When creating your MIME object please observe these common rules:
+ \li Parameters named \c contentType[..] and \c contentDisp[..] and
+ \c contentTEnc[..] will return the values for the respective MIME
+ headers 'Content-Type' and 'Content-Disposition' and
+ 'Content-Transfer-Encoding'. The following applies to these parameters:
+ \li The relevant MIME part may <b>only</b> be created if the respective
+ \c contentType[..] parameter is holding a non-zero-length string. If the
+ \c contentType[..] parameter value is invalid or holding an empty string
+ the respective \c contentDisp[..] and \c contentTEnc[..] parameters
+ should be ignored.
+ \li If the respective \c contentDisp[..] or \c contentTEnc[..] parameter
+ is NULL or holding a zero-length string it is up to you whether you want
+ to add the relevant MIME header yourself, but since it in in the
+ responsibility of the plugin implementors to provide you with all
+ neccessary 'Content-[..]' header information you should <b>not need</b>
+ to define them if they are not returned by the signing or encrypting
+ function - otherwise this may be considered as a bug in the plugin and
+ you could report the missing MIME header information to the address
+ returned by the \c bugURL() function.
+
+ If \c makeMultiMime returns FALSE the \c contentTypeMain returned must
+ not be altered but used to specify a single part mime object holding the
+ code bloc, e.g. this is used for 'enveloped-data' single part MIME
+ objects. In this case you should ignore both the \c content[..]Version
+ and \c content[..]Code parameters.
+
+ If \c makeMultiMime returns TRUE also the following rules apply:
+ \li If \c includeCleartext is TRUE you should include the cleartext
+ as first part of our multipart MIME object, typically this is TRUE
+ when signing mails but FALSE when encrypting.
+ \li The \c contentTypeMain returned typically starts with
+ "multipart/" while providing a "protocol" and a "micalg" parameter: just
+ add an appropriate \c "; boundary=[your \c boundary \c string]" to get
+ the complete Content-Type value to be used for the MIME object embedding
+ both the signed part and the signature part (or - in case of
+ encrypting - the version part and the code part, resp.).
+ \li If \c contentTypeVersion is holding a non-zero-length string an
+ additional MIME part must added immediately before the code part, this
+ version part's MIME headers must have the unaltered values of
+ \c contentTypeVersion and (if they are holding non-zero-length strings)
+ \c contentDispVersion and \c contentTEncVersion, the unaltered contents
+ of \c bodyTextVersion must be it's body.
+ \li The value returned in \c contentTypeCode is specifying the complete
+ Content-Type to be used for this multipart MIME object's signature part
+ (or - in case of encrypting - for the code part following after the
+ version part, resp.), you should not add/change/remove anything here
+ but just use it's unaltered value for specifying the Content-Type header
+ of the respective MIME part.
+ \li The same applies to the \c contentDispCode value: just use it's
+ unaltered value to specify the Content-Disposition header entry of
+ the respective MIME part.
+ \li The same applies to the \c contentTEncCode value: just use it's
+ unaltered value to specify the Content-Transfer-Encoding header of
+ the respective MIME part.
+
+ <b>If</b> value returned in \c makeMimeObject is <b>FALSE</b> the
+ text strings returned in \c flatTextPrefix and \c flatTextPostfix
+ should be used to build a frame around the cleartext and the code
+ bloc holding the signature (or - in case of encrypting - the encoded
+ data bloc, resp.).<br>
+ If \c includeCleartext is TRUE this frame should also include the
+ cleartext as first bloc, this bloc should be divided from the code bloc
+ by the contents of \c flatTextSeparator - typically this is used for
+ signing but not when encrypting.<br>
+ If \c includeCleartext is FALSE you should ignore both the cleartext
+ and the \c flatTextSeparator parameter.
+
+ <b>How to use StructuringInfo data in your program:</b>
+ \li To compose a signed message please act as described below.
+ \li For constructing an encrypted message just replace the
+ \c signMessage() call by the respective \c encryptMessage() call
+ and then proceed exactly the same way.
+ \li In any case make <b>sure</b> to free your \c ciphertext <b>and</b>
+ to call \c free_StructuringInfo() when you are done with processing
+ the data returned by the signing (or encrypting, resp.) function.
+
+\verbatim
+
+ char* ciphertext;
+ StructuringInfo structInf;
+
+ if( ! signMessage( cleartext, &ciphertext, certificate,
+ &structuring ) ) {
+
+ myErrorDialog( "Error: could not sign the message!" );
+
+ } else {
+ if( structInf.makeMimeObject ) {
+
+ // Build the main MIME object.
+ // This is done by
+ // using the header values returned in
+ // structInf.contentTypeMain and in
+ // structInf.contentDispMain and in
+ // structInf.contentTEncMain.
+ ..
+
+ if( ! structInf.makeMultiMime ) {
+
+ // Build the main MIME object's body.
+ // This is done by
+ // using the code bloc returned in
+ // ciphertext.
+ ..
+
+ } else {
+
+ // Build the encapsulated MIME parts.
+ if( structInf.includeCleartext ) {
+
+ // Build a MIME part holding the cleartext.
+ // This is done by
+ // using the original cleartext's headers and by
+ // taking it's original body text.
+ ..
+
+ }
+ if( structInf.contentTypeVersion
+ && 0 < strlen( structInf.contentTypeVersion ) ) {
+
+ // Build a MIME part holding the version information.
+ // This is done by
+ // using the header values returned in
+ // structInf.contentTypeVersion and
+ // structInf.contentDispVersion and
+ // structInf.contentTEncVersion and by
+ // taking the body contents returned in
+ // structInf.bodyTextVersion.
+ ..
+
+ }
+ if( structInf.contentTypeCode
+ && 0 < strlen( structInf.contentTypeCode ) ) {
+
+ // Build a MIME part holding the code information.
+ // This is done by
+ // using the header values returned in
+ // structInf.contentTypeCode and
+ // structInf.contentDispCode and
+ // structInf.contentTEncCode and by
+ // taking the body contents returned in
+ // ciphertext.
+ ..
+
+ } else {
+
+ // Plugin error!
+ myErrorDialog( "Error: Cryptography plugin returned a main"
+ "Content-Type=Multipart/.. but did not "
+ "specify the code bloc's Content-Type header."
+ "\nYou may report this bug:"
+ "\n" + cryptplug.bugURL() );
+ }
+ }
+ } else {
+
+ // Build a plain message body
+ // based on the values returned in structInf.
+ // Note: We do _not_ insert line breaks between the parts since
+ // it is the plugin job to provide us with ready-to-use
+ // texts containing all neccessary line breaks.
+ strcpy( myMessageBody, structInf.plainTextPrefix );
+ if( structInf.includeCleartext ) {
+ strcat( myMessageBody, cleartext );
+ strcat( myMessageBody, structInf.plainTextSeparator );
+ }
+ strcat( myMessageBody, *ciphertext );
+ strcat( myMessageBody, structInf.plainTextPostfix );
+ }
+
+ // free the memory that was allocated
+ // for the ciphertext
+ free( ciphertext );
+
+ // free the memory that was allocated
+ // for our StructuringInfo's char* members
+ free_StructuringInfo( &structuring );
+ }
+
+\endverbatim
+
+ \note Make sure to call \c free_StructuringInfo() when you are done
+ with processing the StructuringInfo data!
+
+ \see free_StructuringInfo
+ \see signMessage, encryptMessage, encryptAndSignMessage
+*/
+struct StructuringInfo {
+ bool includeCleartext; /*!< specifies whether we should include the
+ cleartext as first part of our multipart
+ MIME object (or - for non-MIME
+ messages - as flat text to be set before
+ the ciphertext, resp.), typically this
+ is TRUE when signing mails but FALSE
+ when encrypting<br>
+ (this parameter is relevant no matter
+ whether \c makeMimeObject is TRUE or
+ FALSE) */
+ bool makeMimeObject; /*!< specifies whether we should create a MIME
+ object or a flat text message body */
+ /* the following are used for MIME messages only */
+ bool makeMultiMime; /*!< specifies whether we should create a
+ 'Multipart' MIME object or a single part
+ object, if FALSE only \c contentTypeMain,
+ \c contentDispMain and \c contentTEncMain
+ may be used and all other parameters have
+ to be ignored<br>
+ (ignore this parameter if \c makeMimeObject
+ is FALSE) */
+ char* contentTypeMain; /*!< value of the main 'Content-Type'
+ header<br>
+ (ignore this parameter if \c makeMimeObject
+ is FALSE) */
+ char* contentDispMain; /*!< value of the main 'Content-Disposition'
+ header<br>
+ (ignore this parameter if \c makeMimeObject
+ is FALSE) */
+ char* contentTEncMain; /*!< value of the main
+ 'Content-TransferEncoding' header<br>
+ (ignore this parameter if \c makeMimeObject
+ is FALSE) */
+ char* contentTypeVersion; /*!< 'Content-Type' of the additional version
+ part that might preceed the code part -
+ if NULL or zero length no version part
+ must be created<br>
+ (ignore this parameter if either
+ \c makeMimeObject or \c makeMultiMime
+ is FALSE) */
+ char* contentDispVersion; /*!< 'Content-Disposition' of the additional
+ preceeding the code part (only valid if
+ \c contentTypeVersion holds a
+ non-zero-length string)<br>
+ (ignore this parameter if either
+ \c makeMimeObject or \c makeMultiMime
+ is FALSE or if \c contentTypeVersion does
+ not return a non-zero-length string) */
+ char* contentTEncVersion; /*!< 'Content-Transfer-Encoding' of the
+ additional version part (only valid if
+ \c contentTypeVersion holds a
+ non-zero-length string)<br>
+ (ignore this parameter if either
+ \c makeMimeObject or \c makeMultiMime
+ is FALSE or if \c contentTypeVersion does
+ not return a non-zero-length string) */
+ char* bodyTextVersion; /*!< body text of the additional version part
+ (only valid if \c contentTypeVersion
+ holds a non-zero-length string)<br>
+ (ignore this parameter if either
+ \c makeMimeObject or \c makeMultiMime
+ is FALSE or if \c contentTypeVersion does
+ not return a non-zero-length string) */
+ char* contentTypeCode; /*!< 'Content-Type' of the code part holding
+ the signature code (or the encrypted
+ data, resp.)<br>
+ (ignore this parameter if either
+ \c makeMimeObject or \c makeMultiMime
+ is FALSE) */
+ char* contentDispCode; /*!< 'Content-Disposition' of the code part<br>
+ (ignore this parameter if either
+ \c makeMimeObject or \c makeMultiMime
+ is FALSE or if \c contentTypeCode does
+ not return a non-zero-length string) */
+ char* contentTEncCode; /*!< 'Content-Type' of the code part<br>
+ (ignore this parameter if either
+ \c makeMimeObject or \c makeMultiMime
+ is FALSE or if \c contentTypeCode does
+ not return a non-zero-length string) */
+ /* the following are used for flat non-MIME messages only */
+ char* flatTextPrefix; /*!< text to preceed the main text (or the
+ code bloc containing the encrypted main
+ text, resp.)<br>
+ (ignore this parameter if
+ \c makeMimeObject is TRUE) */
+ char* flatTextSeparator; /*!< text to be put between the main text and
+ the signature code bloc (not used when
+ encrypting)<br>
+ (ignore this parameter if
+ \c makeMimeObject is TRUE or if
+ \c includeCleartext is FALSE) */
+ char* flatTextPostfix; /*!< text to follow the signature code bloc
+ (or the encrypted data bloc, resp.)<br>
+ (ignore this parameter if
+ \c makeMimeObject is TRUE) */
+};
+
+
+/*! \ingroup groupAdUsoInterno
+ \brief If you are not planning to write your own cryptography
+ plugin <b>you should ignore this</b> function!
+
+ Usage of this function is depreciated for plugin users but highly
+ recommended for plugin implementors since this is an internal
+ function for initializing all char* members of a \c StructuringInfo
+ struct.<br>
+ This function <b>must</b> be called in <b>any</b> plugin's
+ implementations of the following functions:
+
+ \c signMessage() <br>
+ \c encryptMessage() <br>
+ \c encryptAndSignMessage()
+
+ Calling this function makes sure the corresponding
+ \c free_StructuringInfo() calls which will be embedded by
+ your plugin's users into their code will be able to
+ determine which of the char* members belonging to the
+ respective's StructuringInfo had been allocated memory
+ for during previous signing or encrypting actions.
+
+ \see free_StructuringInfo, StructuringInfo
+ \see signMessage, encryptMessage, encryptAndSignMessage
+*/
+ inline void init_StructuringInfo( struct StructuringInfo* s )
+ {
+ if( ! s ) return;
+
+ s->includeCleartext = false;
+
+ s->makeMimeObject = false;
+ s->makeMultiMime = false;
+
+ s->contentTypeMain = 0;
+ s->contentDispMain = 0;
+ s->contentTEncMain = 0;
+
+ s->contentTypeVersion = 0;
+ s->contentDispVersion = 0;
+ s->contentTEncVersion = 0;
+ s->bodyTextVersion = 0;
+
+ s->contentTypeCode = 0;
+ s->contentDispCode = 0;
+ s->contentTEncCode = 0;
+
+ s->flatTextPrefix = 0;
+ s->flatTextSeparator = 0;
+ s->flatTextPostfix = 0;
+ }
+
+/*! \ingroup groupSignCryptAct
+ \brief Important method for freeing all memory that was allocated
+ for the char* members of a \c StructuringInfo struct - use
+ this function after <b>each</b> signing or encrypting function
+ call.
+
+ \note Even when intending to call \c encryptMessage() immediately
+ after having called \c signMessage() you first <b>must</b> call
+ the \c free_StructuringInfo() function to make sure all memory is
+ set free that was allocated for your StructuringInfo's char* members
+ by the \c signMessage() function!
+
+ \see StructuringInfo
+*/
+ inline void free_StructuringInfo( struct StructuringInfo* s )
+ {
+ if( ! s ) return;
+ if( s->contentTypeMain ) free( s->contentTypeMain );
+ if( s->contentDispMain ) free( s->contentDispMain );
+ if( s->contentTEncMain ) free( s->contentTEncMain );
+ if( s->contentTypeVersion ) free( s->contentTypeVersion );
+ if( s->contentDispVersion ) free( s->contentDispVersion );
+ if( s->contentTEncVersion ) free( s->contentTEncVersion );
+ if( s->bodyTextVersion ) free( s->bodyTextVersion );
+ if( s->contentTypeCode ) free( s->contentTypeCode );
+ if( s->contentDispCode ) free( s->contentDispCode );
+ if( s->contentTEncCode ) free( s->contentTEncCode );
+ if( s->flatTextPrefix ) free( s->flatTextPrefix );
+ if( s->flatTextSeparator ) free( s->flatTextSeparator );
+ if( s->flatTextPostfix ) free( s->flatTextPostfix );
+ }
+
+
+/*! \ingroup groupSignAct
+ \brief Signs a message \c cleartext and returns
+ in \c *ciphertext the signature data bloc that
+ is to be added to the message. The length returned
+ in \c *cipherLen tells you the size (==amount of bytes)
+ of the ciphertext, if the structuring information
+ would return with contentTEncCode set to "base64"
+ the ciphertext might contain a char 0x00
+ and has to be converted into base64 before sending.
+
+ The signature role is specified by \c certificate.
+ If \c certificate is \c NULL, the default certificate is used.
+
+ If the message could be signed, the function returns
+ \c true, otherwise
+ \c false.
+
+ Use the StructuringInfo data returned in parameter \c structuring
+ to find out how to build the respective MIME object (or the plain
+ text message body, resp.).
+
+ \note The function allocates memory for the \c *ciphertext, so
+ make sure you set free that memory when no longer needing
+ it (as shown in example code provided with documentation
+ of the struct \c StructuringInfo).
+
+ \note The function also allocates memory for some char* members
+ of the StructuringInfo* parameter that you are providing,
+ therefore you <b>must</b> call the \c free_StructuringInfo() function
+ to make sure all memory is set free that was allocated. This must be
+ done <b>before</b> calling the next cryptography function - even if
+ you intend to call \c encryptMessage() immediately after
+ \c signMessage().
+
+ \see StructuringInfo, free_StructuringInfo
+*/
+bool signMessage( const char* cleartext,
+ char** ciphertext,
+ const size_t* cipherLen,
+ const char* certificate,
+ struct StructuringInfo* structuring,
+ int* errId,
+ char** errTxt );
+
+
+/*! \ingroup groupSignAct
+ */
+struct SignatureMetaDataExtendedInfo
+{
+ struct tm* creation_time;
+ SigStatusFlags sigStatusFlags;
+ char* status_text;
+ char* keyid;
+ char* fingerprint;
+ char* algo;
+ char* userid;
+ char* name;
+ char* comment;
+ char** emailList;
+ int emailCount;
+ unsigned long algo_num;
+ unsigned long validity;
+ unsigned long userid_num;
+ unsigned long keylen;
+ unsigned long key_created;
+ unsigned long key_expires;
+};
+
+/*! \ingroup groupSignAct
+*/
+struct SignatureMetaData {
+ char* status;
+ struct SignatureMetaDataExtendedInfo* extended_info;
+ int extended_info_count;
+ char* nota_xml;
+ int status_code;
+};
+
+/*! \ingroup groupSignAct
+ \brief Checks whether the signature of a message is
+ valid.
+
+ \c cleartext must never be 0 but be a valid pointer.
+
+ If \c *cleartext > 0 then **cleartext specifies the message text
+ that was signed and \c signaturetext is the signature itself.
+
+ If \c *cleartext == 0 is an empty string then \c signaturetext is
+ supposed to contain an opaque signed message part. After checking the
+ data and verifying the signature the cleartext of the message will be
+ returned in \c cleartext. The user must free the respective memory
+ ocupied by *cleartext.
+
+ Depending on the configuration, MUAs might not need to use this.
+ If \c sigmeta is non-null, the
+ \c SignatureMetaData object pointed to will
+ contain meta information about the signature after the
+ function call.
+*/
+bool checkMessageSignature( char** cleartext,
+ const char* signaturetext,
+ bool signatureIsBinary,
+ int signatureLen,
+ struct SignatureMetaData* sigmeta );
+
+/*! \ingroup groupSignAct
+ \brief Stores the certificates that follow with the message
+ \c ciphertext locally.
+*/
+bool storeCertificatesFromMessage( const char* ciphertext );
+
+
+/*! \ingroup groupCryptAct
+ \brief Find all certificate for a given addressee.
+
+ NOTE: The certificate parameter must point to a not-yet allocated
+ char*. The function will allocate the memory needed and
+ return the size in newSize.
+ If secretOnly is true, only secret keys are returned.
+*/
+bool findCertificates( const char* addressee,
+ char** certificates,
+ int* newSize,
+ bool secretOnly );
+
+/*! \ingroup groupCryptAct
+ \brief Encrypts an email message in
+ \c cleartext according to the \c addressee and
+ the current settings (algorithm, etc.) and
+ returns the encoded data bloc in \c *ciphertext.
+ The length returned in \c *cipherLen tells you the
+ size (==amount of bytes) of the ciphertext, if the
+ structuring information would return with
+ contentTEncCode set to "base64" the ciphertext
+ might contain a char 0x00 and has to be converted
+ into base64 before sending.
+
+ If the message could be encrypted, the function returns
+ \c true, otherwise
+ \c false.
+
+ Use the StructuringInfo data returned in parameter \c structuring
+ to find out how to build the respective MIME object (or the plain
+ text message body, resp.).
+
+ \note The function allocates memory for the \c *ciphertext, so
+ make sure you set free that memory when no longer needing
+ it (as shown in example code provided with documentation
+ of the struct \c StructuringInfo).
+
+ \note The function also allocates memory for some char* members
+ of the StructuringInfo* parameter that you are providing,
+ therefore you <b>must</b> call the \c free_StructuringInfo() function
+ to make sure all memory is set free that was allocated. This must be
+ done <b>before</b> calling the next cryptography function!
+
+ \see StructuringInfo, free_StructuringInfo
+*/
+bool encryptMessage( const char* cleartext,
+ const char** ciphertext,
+ const size_t* cipherLen,
+ const char* addressee,
+ struct StructuringInfo* structuring,
+ int* errId,
+ char** errTxt );
+
+
+/*! \ingroup groupCryptAct
+ \brief Combines the functionality of
+ \c encryptMessage() and
+ \c signMessage().
+
+ If \c certificate is \c NULL,
+ the default certificate will be used.
+
+ If the message could be signed and encrypted, the function returns
+ \c true, otherwise
+ \c false.
+
+ Use the StructuringInfo data returned in parameter \c structuring
+ to find out how to build the respective MIME object (or the plain
+ text message body, resp.).
+
+ \note The function allocates memory for the \c *ciphertext, so
+ make sure you set free that memory when no longer needing
+ it (as shown in example code provided with documentation
+ of the struct \c StructuringInfo).
+
+ \note The function also allocates memory for some char* members
+ of the StructuringInfo* parameter that you are providing,
+ therefore you <b>must</b> call the \c free_StructuringInfo() function
+ to make sure all memory is set free that was allocated. This must be
+ done <b>before</b> calling the next cryptography function!
+
+ \see StructuringInfo, free_StructuringInfo
+*/
+bool encryptAndSignMessage( const char* cleartext,
+ const char** ciphertext,
+ const char* certificate,
+ struct StructuringInfo* structuring );
+
+/*! \ingroup groupCryptAct
+ \brief Tries to decrypt an email message
+ \c ciphertext and returns the decrypted
+ message in \c cleartext.
+
+ The \c certificate is used for decryption. If
+ the message could be decrypted, the function returns
+ \c true, otherwise
+ \c false.
+*/
+bool decryptMessage( const char* ciphertext,
+ bool cipherIsBinary,
+ int cipherLen,
+ const char** cleartext,
+ const char* certificate,
+ int* errId,
+ char** errTxt );
+
+/*! \ingroup groupCryptAct
+ \brief Combines the functionality of
+ \c checkMessageSignature() and
+ \c decryptMessage().
+
+ If \c certificate is \c NULL,
+ the default certificate will be used.
+ If \c sigmeta is non-null, the \c SignatureMetaData
+ object pointed to will contain meta information about
+ the signature after the function call.
+*/
+bool decryptAndCheckMessage( const char* ciphertext,
+ bool cipherIsBinary,
+ int cipherLen,
+ const char** cleartext,
+ const char* certificate,
+ bool* signatureFound,
+ struct SignatureMetaData* sigmeta,
+ int* errId,
+ char** errTxt );
+
+
+/*! \ingroup groupCertAct
+ \brief This function returns an XML representation of a dialog
+ that can be used to fill in the data for requesting a
+ certificate (which in turn is done with the function
+ \c requestCertificate() described
+ next.
+*/
+const char* requestCertificateDialog( void );
+
+/*! \ingroup groupCertAct
+ \brief Generates a prototype certificate with the data provided
+ in the four parameter. The memory returned in \a generatedKey
+ must be freed with free() by the caller.
+*/
+bool requestDecentralCertificate( const char* certparms,
+ char** generatedKey, int* keyLength );
+
+/*! \ingroup groupCertAct
+ \brief Requests a certificate in a PSE from the CA
+ specified in \c ca_address.
+*/
+bool requestCentralCertificateAndPSE( const char* name,
+ const char* email, const char* organization, const char* department,
+ const char* ca_address );
+
+/*! \ingroup groupCertAct
+ \brief Creates a local PSE.
+*/
+bool createPSE( void );
+
+/*! \ingroup groupCertAct
+ \brief Parses and adds a certificate returned by a CA upon
+ request with
+ \c requestDecentralCertificate() or
+ \c requestCentralCertificate().
+
+ If the certificate was requested with
+ \c requestCentralCertificate(), the
+ certificate returned will come complete with a PSE which is
+ also registered with this method.
+*/
+bool registerCertificate( const char* );
+
+/*! \ingroup groupCertAct
+ \brief Requests the prolongation of the certificate
+ \c certificate from the CA
+ \c ca_address.
+*/
+bool requestCertificateProlongation( const char*
+ certificate, const char* ca_address );
+
+/*! \ingroup groupCertAct
+ \brief Returns an HTML 2-formatted string that describes the
+ certificate chain of the user's certificate.
+
+ Data displayed is at least the issuer of the certificate, the serial number
+ of the certificate, the owner of the certificate, the checksum
+ of the certificate, the validity duration of the certificate,
+ the usage of the certificate, and the contained email
+ addresses, if any.
+*/
+const char* certificateChain( void );
+
+/*! \ingroup groupCertAct
+ \brief Deletes the specified user certificate from the current
+ PSE.
+*/
+bool deleteCertificate( const char* certificate );
+
+/*! \ingroup groupCertAct
+ \brief Archives the specified user certificate in the current PSE.
+
+ The certificate cannot be used any longer after this
+ operation unless it is unarchived.
+*/
+bool archiveCertificate( const char* certificate );
+
+
+/*! \ingroup groupCRLAct
+ \brief Returns a HTML 2-formatted string that describes the
+ CRL, suitable for display in the MUA.
+*/
+const char* displayCRL( void );
+
+/*! \ingroup groupCRLAct
+ \brief Manually update the CRL. CRLs will also be automatically
+ updated on demand by the backend.
+
+ If there is a local version of a CRL saved, it will be overwritten
+ with the new CRL from the CA.
+*/
+void updateCRL( void );
+
+struct CertIterator;
+
+struct DnPair {
+ char *key;
+ char *value;
+};
+
+struct CertificateInfo {
+ char** userid;
+ char* serial;
+ char* fingerprint;
+
+ char* issuer;
+ char* chainid;
+
+ char* caps;
+
+ unsigned long created;
+ unsigned long expire;
+
+ int secret : 1;
+ int invalid : 1;
+ int expired : 1;
+ int disabled : 1;
+
+
+ struct DnPair *dnarray; /* parsed values from userid[0] */
+};
+
+/*! \function struct CertIterator* startListCertificates( const char* pattern );
+ \function struct CertificateInfo* nextCertificate( struct CertIterator* );
+ \function void endListCertificates( struct CertIterator* );
+
+ \ingroup certList
+ Example that runs through certs matching "Steffen":
+\verbatim
+ struct CertificateInfo* info;
+ struct CertIterator* it = startListCertificates("Steffen", 0 );
+ while( nextCertificate( it, &info ) == GPGME_No_Error && info ) {
+ do something with info.
+ dont free() it, the struct will be reused
+ by the next call to nextCertificate()
+ }
+ int truncated = endListCertificates( it );
+\endverbatim
+*/
+struct CertIterator*
+startListCertificates( const char* pattern, int remote );
+
+int
+nextCertificate( struct CertIterator*, struct CertificateInfo** result );
+
+int
+endListCertificates( struct CertIterator* );
+
+/*!
+ Import a certificate that was a result from a search-operation using the startListCertificates(), nextCertificate() funtions.
+
+ The fingerprint must be passed to identify the key.
+
+ Additional info about the import operation is available in the additional_info parameter. The string must be free'd by the user with free().
+ */
+
+int
+importCertificateWithFPR( const char* fingerprint, char** additional_info );
+
+/*!
+ Import a certificate from memory.
+
+ Additional info about the import operation is available in the additional_info parameter. The string must be free'd by the user with free().
+*/
+int
+importCertificateFromMem( const char* data, size_t length, char** additional_info );
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*CRYPTPLUG_H*/
+
diff --git a/branches/gpgme-0-3-branch/gpgmeplug/gpgme-openpgp.c b/branches/gpgme-0-3-branch/gpgmeplug/gpgme-openpgp.c
new file mode 100644
index 00000000..c8e0234f
--- /dev/null
+++ b/branches/gpgme-0-3-branch/gpgmeplug/gpgme-openpgp.c
@@ -0,0 +1,60 @@
+#define GPGMEPLUG_PROTOCOL GPGME_PROTOCOL_OpenPGP
+
+/* definitions for signing */
+// 1. opaque signatures (only used for S/MIME)
+#define GPGMEPLUG_OPA_SIGN_INCLUDE_CLEARTEXT false
+#define GPGMEPLUG_OPA_SIGN_MAKE_MIME_OBJECT false
+#define GPGMEPLUG_OPA_SIGN_MAKE_MULTI_MIME false
+#define GPGMEPLUG_OPA_SIGN_CTYPE_MAIN ""
+#define GPGMEPLUG_OPA_SIGN_CDISP_MAIN ""
+#define GPGMEPLUG_OPA_SIGN_CTENC_MAIN ""
+#define GPGMEPLUG_OPA_SIGN_CTYPE_VERSION ""
+#define GPGMEPLUG_OPA_SIGN_CDISP_VERSION ""
+#define GPGMEPLUG_OPA_SIGN_CTENC_VERSION ""
+#define GPGMEPLUG_OPA_SIGN_BTEXT_VERSION ""
+#define GPGMEPLUG_OPA_SIGN_CTYPE_CODE ""
+#define GPGMEPLUG_OPA_SIGN_CDISP_CODE ""
+#define GPGMEPLUG_OPA_SIGN_CTENC_CODE ""
+#define GPGMEPLUG_OPA_SIGN_FLAT_PREFIX ""
+#define GPGMEPLUG_OPA_SIGN_FLAT_SEPARATOR ""
+#define GPGMEPLUG_OPA_SIGN_FLAT_POSTFIX ""
+// 2. detached signatures (used for S/MIME and for OpenPGP)
+#define GPGMEPLUG_DET_SIGN_INCLUDE_CLEARTEXT true
+#define GPGMEPLUG_DET_SIGN_MAKE_MIME_OBJECT true
+#define GPGMEPLUG_DET_SIGN_MAKE_MULTI_MIME true
+#define GPGMEPLUG_DET_SIGN_CTYPE_MAIN "multipart/signed; protocol=\"application/pgp-signature\"; micalg=pgp-sha1"
+#define GPGMEPLUG_DET_SIGN_CDISP_MAIN ""
+#define GPGMEPLUG_DET_SIGN_CTENC_MAIN ""
+#define GPGMEPLUG_DET_SIGN_CTYPE_VERSION ""
+#define GPGMEPLUG_DET_SIGN_CDISP_VERSION ""
+#define GPGMEPLUG_DET_SIGN_CTENC_VERSION ""
+#define GPGMEPLUG_DET_SIGN_BTEXT_VERSION ""
+#define GPGMEPLUG_DET_SIGN_CTYPE_CODE "application/pgp-signature"
+#define GPGMEPLUG_DET_SIGN_CDISP_CODE ""
+#define GPGMEPLUG_DET_SIGN_CTENC_CODE ""
+#define GPGMEPLUG_DET_SIGN_FLAT_PREFIX ""
+#define GPGMEPLUG_DET_SIGN_FLAT_SEPARATOR ""
+#define GPGMEPLUG_DET_SIGN_FLAT_POSTFIX ""
+// 3. common definitions for opaque and detached signing
+#define __GPGMEPLUG_SIGNATURE_CODE_IS_BINARY false
+
+/* definitions for encoding */
+#define GPGMEPLUG_ENC_INCLUDE_CLEARTEXT false
+#define GPGMEPLUG_ENC_MAKE_MIME_OBJECT true
+#define GPGMEPLUG_ENC_MAKE_MULTI_MIME true
+#define GPGMEPLUG_ENC_CTYPE_MAIN "multipart/encrypted; protocol=\"application/pgp-encrypted\""
+#define GPGMEPLUG_ENC_CDISP_MAIN ""
+#define GPGMEPLUG_ENC_CTENC_MAIN ""
+#define GPGMEPLUG_ENC_CTYPE_VERSION "application/pgp-encrypted"
+#define GPGMEPLUG_ENC_CDISP_VERSION "attachment"
+#define GPGMEPLUG_ENC_CTENC_VERSION ""
+#define GPGMEPLUG_ENC_BTEXT_VERSION "Version: 1"
+#define GPGMEPLUG_ENC_CTYPE_CODE "application/octet-stream"
+#define GPGMEPLUG_ENC_CDISP_CODE "inline; filename=\"msg.asc\""
+#define GPGMEPLUG_ENC_CTENC_CODE ""
+#define GPGMEPLUG_ENC_FLAT_PREFIX ""
+#define GPGMEPLUG_ENC_FLAT_SEPARATOR ""
+#define GPGMEPLUG_ENC_FLAT_POSTFIX ""
+#define __GPGMEPLUG_ENCRYPTED_CODE_IS_BINARY false
+
+#include "gpgmeplug.c"
diff --git a/branches/gpgme-0-3-branch/gpgmeplug/gpgme-smime.c b/branches/gpgme-0-3-branch/gpgmeplug/gpgme-smime.c
new file mode 100644
index 00000000..f45354b3
--- /dev/null
+++ b/branches/gpgme-0-3-branch/gpgmeplug/gpgme-smime.c
@@ -0,0 +1,60 @@
+#define GPGMEPLUG_PROTOCOL GPGME_PROTOCOL_CMS
+
+/* definitions for signing */
+// 1. opaque signatures (only used for S/MIME)
+#define GPGMEPLUG_OPA_SIGN_INCLUDE_CLEARTEXT false
+#define GPGMEPLUG_OPA_SIGN_MAKE_MIME_OBJECT true
+#define GPGMEPLUG_OPA_SIGN_MAKE_MULTI_MIME false
+#define GPGMEPLUG_OPA_SIGN_CTYPE_MAIN "application/pkcs7-mime; smime-type=signed-data; name=\"smime.p7m\""
+#define GPGMEPLUG_OPA_SIGN_CDISP_MAIN "attachment; filename=\"smime.p7m\""
+#define GPGMEPLUG_OPA_SIGN_CTENC_MAIN "base64"
+#define GPGMEPLUG_OPA_SIGN_CTYPE_VERSION ""
+#define GPGMEPLUG_OPA_SIGN_CDISP_VERSION ""
+#define GPGMEPLUG_OPA_SIGN_CTENC_VERSION ""
+#define GPGMEPLUG_OPA_SIGN_BTEXT_VERSION ""
+#define GPGMEPLUG_OPA_SIGN_CTYPE_CODE ""
+#define GPGMEPLUG_OPA_SIGN_CDISP_CODE ""
+#define GPGMEPLUG_OPA_SIGN_CTENC_CODE ""
+#define GPGMEPLUG_OPA_SIGN_FLAT_PREFIX ""
+#define GPGMEPLUG_OPA_SIGN_FLAT_SEPARATOR ""
+#define GPGMEPLUG_OPA_SIGN_FLAT_POSTFIX ""
+// 2. detached signatures (used for S/MIME and for OpenPGP)
+#define GPGMEPLUG_DET_SIGN_INCLUDE_CLEARTEXT true
+#define GPGMEPLUG_DET_SIGN_MAKE_MIME_OBJECT true
+#define GPGMEPLUG_DET_SIGN_MAKE_MULTI_MIME true
+#define GPGMEPLUG_DET_SIGN_CTYPE_MAIN "multipart/signed; protocol=\"application/pkcs7-signature\"; micalg=sha1"
+#define GPGMEPLUG_DET_SIGN_CDISP_MAIN ""
+#define GPGMEPLUG_DET_SIGN_CTENC_MAIN ""
+#define GPGMEPLUG_DET_SIGN_CTYPE_VERSION ""
+#define GPGMEPLUG_DET_SIGN_CDISP_VERSION ""
+#define GPGMEPLUG_DET_SIGN_CTENC_VERSION ""
+#define GPGMEPLUG_DET_SIGN_BTEXT_VERSION ""
+#define GPGMEPLUG_DET_SIGN_CTYPE_CODE "application/pkcs7-signature; name=\"smime.p7s\""
+#define GPGMEPLUG_DET_SIGN_CDISP_CODE "attachment; filename=\"smime.p7s\""
+#define GPGMEPLUG_DET_SIGN_CTENC_CODE "base64"
+#define GPGMEPLUG_DET_SIGN_FLAT_PREFIX ""
+#define GPGMEPLUG_DET_SIGN_FLAT_SEPARATOR ""
+#define GPGMEPLUG_DET_SIGN_FLAT_POSTFIX ""
+// 3. common definitions for opaque and detached signing
+#define __GPGMEPLUG_SIGNATURE_CODE_IS_BINARY true
+
+/* definitions for encoding */
+#define GPGMEPLUG_ENC_INCLUDE_CLEARTEXT false
+#define GPGMEPLUG_ENC_MAKE_MIME_OBJECT true
+#define GPGMEPLUG_ENC_MAKE_MULTI_MIME false
+#define GPGMEPLUG_ENC_CTYPE_MAIN "application/pkcs7-mime; smime-type=enveloped-data; name=\"smime.p7m\""
+#define GPGMEPLUG_ENC_CDISP_MAIN "attachment; filename=\"smime.p7m\""
+#define GPGMEPLUG_ENC_CTENC_MAIN "base64"
+#define GPGMEPLUG_ENC_CTYPE_VERSION ""
+#define GPGMEPLUG_ENC_CDISP_VERSION ""
+#define GPGMEPLUG_ENC_CTENC_VERSION ""
+#define GPGMEPLUG_ENC_BTEXT_VERSION ""
+#define GPGMEPLUG_ENC_CTYPE_CODE ""
+#define GPGMEPLUG_ENC_CDISP_CODE ""
+#define GPGMEPLUG_ENC_CTENC_CODE ""
+#define GPGMEPLUG_ENC_FLAT_PREFIX ""
+#define GPGMEPLUG_ENC_FLAT_SEPARATOR ""
+#define GPGMEPLUG_ENC_FLAT_POSTFIX ""
+#define __GPGMEPLUG_ENCRYPTED_CODE_IS_BINARY true
+
+#include "gpgmeplug.c"
diff --git a/branches/gpgme-0-3-branch/gpgmeplug/gpgmeplug.c b/branches/gpgme-0-3-branch/gpgmeplug/gpgmeplug.c
new file mode 100644
index 00000000..03d3dbe5
--- /dev/null
+++ b/branches/gpgme-0-3-branch/gpgmeplug/gpgmeplug.c
@@ -0,0 +1,2863 @@
+/* -*- Mode: C -*-
+
+ $Id$
+
+ GPGMEPLUG - an GPGME based cryptography plug-in following
+ the common CRYPTPLUG specification.
+
+ Copyright (C) 2001 by Klar�lvdalens Datakonsult AB
+ Copyright (C) 2002 g10 Code GmbH
+
+ GPGMEPLUG is free software; you can redistribute it and/or modify
+ it under the terms of GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ GPGMEPLUG is distributed in the hope that it will be useful,
+ it under the terms of GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+*/
+
+
+
+/*! \file gpgmeplug.c
+ \brief GPGME implementation of CRYPTPLUG following the
+ specification located in common API header cryptplug.h.
+
+ CRYPTPLUG is an independent cryptography plug-in API
+ developed for Sphinx-enabeling KMail and Mutt.
+
+ CRYPTPLUG was designed for the Aegypten project, but it may
+ be used by 3rd party developers as well to design pluggable
+ crypto backends for the above mentioned MUAs.
+
+ \note All string parameters appearing in this API are to be
+ interpreted as UTF-8 encoded.
+
+ \see cryptplug.h
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <time.h>
+#include <ctype.h>
+
+#ifndef BUG_URL
+#define BUG_URL "http:://www.gnupg.org/aegypten/"
+#endif
+
+#include "gpgme.h"
+#ifndef GPGMEPLUG_PROTOCOL
+#define GPGMEPLUG_PROTOCOL GPGME_PROTOCOL_OpenPGP
+#endif
+
+/* definitions for signing */
+/* 1. opaque signatures (only used for S/MIME). */
+#ifndef GPGMEPLUG_OPA_SIGN_MAKE_MIME_OBJECT
+#define GPGMEPLUG_OPA_SIGN_INCLUDE_CLEARTEXT false
+#define GPGMEPLUG_OPA_SIGN_MAKE_MIME_OBJECT false
+#define GPGMEPLUG_OPA_SIGN_MAKE_MULTI_MIME false
+#define GPGMEPLUG_OPA_SIGN_CTYPE_MAIN ""
+#define GPGMEPLUG_OPA_SIGN_CDISP_MAIN ""
+#define GPGMEPLUG_OPA_SIGN_CTENC_MAIN ""
+#define GPGMEPLUG_OPA_SIGN_CTYPE_VERSION ""
+#define GPGMEPLUG_OPA_SIGN_CDISP_VERSION ""
+#define GPGMEPLUG_OPA_SIGN_CTENC_VERSION ""
+#define GPGMEPLUG_OPA_SIGN_BTEXT_VERSION ""
+#define GPGMEPLUG_OPA_SIGN_CTYPE_CODE ""
+#define GPGMEPLUG_OPA_SIGN_CDISP_CODE ""
+#define GPGMEPLUG_OPA_SIGN_CTENC_CODE ""
+#define GPGMEPLUG_OPA_SIGN_FLAT_PREFIX ""
+#define GPGMEPLUG_OPA_SIGN_FLAT_SEPARATOR ""
+#define GPGMEPLUG_OPA_SIGN_FLAT_POSTFIX ""
+#endif
+/* 2. detached signatures (used for S/MIME and for OpenPGP) */
+#ifndef GPGMEPLUG_DET_SIGN_MAKE_MIME_OBJECT
+#define GPGMEPLUG_DET_SIGN_INCLUDE_CLEARTEXT true
+#define GPGMEPLUG_DET_SIGN_MAKE_MIME_OBJECT true
+#define GPGMEPLUG_DET_SIGN_MAKE_MULTI_MIME true
+#define GPGMEPLUG_DET_SIGN_CTYPE_MAIN "multipart/signed;protocol=application/pgp-signature;micalg=pgp-sha1"
+#define GPGMEPLUG_DET_SIGN_CDISP_MAIN ""
+#define GPGMEPLUG_DET_SIGN_CTENC_MAIN ""
+#define GPGMEPLUG_DET_SIGN_CTYPE_VERSION ""
+#define GPGMEPLUG_DET_SIGN_CDISP_VERSION ""
+#define GPGMEPLUG_DET_SIGN_CTENC_VERSION ""
+#define GPGMEPLUG_DET_SIGN_BTEXT_VERSION ""
+#define GPGMEPLUG_DET_SIGN_CTYPE_CODE "application/pgp-signature"
+#define GPGMEPLUG_DET_SIGN_CDISP_CODE ""
+#define GPGMEPLUG_DET_SIGN_CTENC_CODE ""
+#define GPGMEPLUG_DET_SIGN_FLAT_PREFIX ""
+#define GPGMEPLUG_DET_SIGN_FLAT_SEPARATOR ""
+#define GPGMEPLUG_DET_SIGN_FLAT_POSTFIX ""
+#endif
+/* 3. common definitions for opaque and detached signing */
+#ifndef __GPGMEPLUG_SIGNATURE_CODE_IS_BINARY
+#define __GPGMEPLUG_SIGNATURE_CODE_IS_BINARY false
+#endif
+
+#define __GPGMEPLUG_ERROR_CLEARTEXT_IS_ZERO "Error: Cannot run checkMessageSignature() with cleartext == 0"
+
+/* definitions for encoding */
+#ifndef GPGMEPLUG_ENC_MAKE_MIME_OBJECT
+#define GPGMEPLUG_ENC_INCLUDE_CLEARTEXT false
+#define GPGMEPLUG_ENC_MAKE_MIME_OBJECT true
+#define GPGMEPLUG_ENC_MAKE_MULTI_MIME true
+#define GPGMEPLUG_ENC_CTYPE_MAIN "multipart/encrypted; protocol=application/pgp-encrypted"
+#define GPGMEPLUG_ENC_CDISP_MAIN ""
+#define GPGMEPLUG_ENC_CTENC_MAIN ""
+#define GPGMEPLUG_ENC_CTYPE_VERSION "application/pgp-encrypted"
+#define GPGMEPLUG_ENC_CDISP_VERSION "attachment"
+#define GPGMEPLUG_ENC_CTENC_VERSION ""
+#define GPGMEPLUG_ENC_BTEXT_VERSION "Version: 1"
+#define GPGMEPLUG_ENC_CTYPE_CODE "application/octet-stream"
+#define GPGMEPLUG_ENC_CDISP_CODE "inline; filename=\"msg.asc\""
+#define GPGMEPLUG_ENC_CTENC_CODE ""
+#define GPGMEPLUG_ENC_FLAT_PREFIX ""
+#define GPGMEPLUG_ENC_FLAT_SEPARATOR ""
+#define GPGMEPLUG_ENC_FLAT_POSTFIX ""
+#define __GPGMEPLUG_ENCRYPTED_CODE_IS_BINARY false
+#endif
+/* Note: The following specification will result in
+ function encryptAndSignMessage() producing
+ _empty_ mails.
+ This must be changed as soon as our plugin
+ is supporting the encryptAndSignMessage() function. */
+#ifndef GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT
+#define GPGMEPLUG_ENCSIGN_INCLUDE_CLEARTEXT false
+#define GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT false
+#define GPGMEPLUG_ENCSIGN_MAKE_MULTI_MIME false
+#define GPGMEPLUG_ENCSIGN_CTYPE_MAIN ""
+#define GPGMEPLUG_ENCSIGN_CDISP_MAIN ""
+#define GPGMEPLUG_ENCSIGN_CTENC_MAIN ""
+#define GPGMEPLUG_ENCSIGN_CTYPE_VERSION ""
+#define GPGMEPLUG_ENCSIGN_CDISP_VERSION ""
+#define GPGMEPLUG_ENCSIGN_CTENC_VERSION ""
+#define GPGMEPLUG_ENCSIGN_BTEXT_VERSION ""
+#define GPGMEPLUG_ENCSIGN_CTYPE_CODE ""
+#define GPGMEPLUG_ENCSIGN_CDISP_CODE ""
+#define GPGMEPLUG_ENCSIGN_CTENC_CODE ""
+#define GPGMEPLUG_ENCSIGN_FLAT_PREFIX ""
+#define GPGMEPLUG_ENCSIGN_FLAT_SEPARATOR ""
+#define GPGMEPLUG_ENCSIGN_FLAT_POSTFIX ""
+#endif
+
+#include "cryptplug.h"
+
+
+#define days_from_seconds(x) ((x)/86400)
+
+
+typedef struct {
+ const char* bugURL;
+ const char* signatureKeyCertificate;
+ SignatureAlgorithm signatureAlgorithm;
+ SignatureCompoundMode signatureCompoundMode;
+ SendCertificates sendCertificates;
+ SignEmail signEmail;
+ bool saveSentSignatures;
+ bool warnNoCertificate;
+ PinRequests numPINRequests;
+ bool checkSignatureCertificatePathToRoot;
+ bool signatureUseCRLs;
+ EncryptionAlgorithm encryptionAlgorithm;
+ EncryptEmail encryptEmail;
+ bool saveMessagesEncrypted;
+ bool checkEncryptionCertificatePathToRoot;
+ bool encryptionUseCRLs;
+ bool encryptionCRLExpiryNearWarning;
+ int encryptionCRLNearExpiryInterval;
+ struct DirectoryServer *directoryServers;
+ unsigned int numDirectoryServers;
+ CertificateSource certificateSource;
+ CertificateSource cRLSource;
+ bool warnSendUnsigned;
+ int numPINRequestsInterval;
+ bool signatureCertificateExpiryNearWarning;
+ int signatureCertificateExpiryNearInterval;
+ bool cACertificateExpiryNearWarning;
+ int cACertificateExpiryNearInterval;
+ bool rootCertificateExpiryNearWarning;
+ int rootCertificateExpiryNearInterval;
+ bool warnSendUnencrypted;
+ bool checkCertificatePath;
+ bool receiverCertificateExpiryNearWarning;
+ int receiverCertificateExpiryNearWarningInterval;
+ bool certificateInChainExpiryNearWarning;
+ int certificateInChainExpiryNearWarningInterval;
+ bool receiverEmailAddressNotInCertificateWarning;
+ const char* libVersion; /* a statically allocated string with the GPGME Version used */
+} Config;
+
+
+Config config;
+
+#define NEAR_EXPIRY 14
+
+/* Max number of parts in a DN */
+#define MAX_GPGME_IDX 20
+
+/* some macros to replace ctype ones and avoid locale problems */
+#define spacep(p) (*(p) == ' ' || *(p) == '\t')
+#define digitp(p) (*(p) >= '0' && *(p) <= '9')
+#define hexdigitp(a) (digitp (a) \
+ || (*(a) >= 'A' && *(a) <= 'F') \
+ || (*(a) >= 'a' && *(a) <= 'f'))
+/* the atoi macros assume that the buffer has only valid digits */
+#define atoi_1(p) (*(p) - '0' )
+#define atoi_2(p) ((atoi_1(p) * 10) + atoi_1((p)+1))
+#define atoi_4(p) ((atoi_2(p) * 100) + atoi_2((p)+2))
+#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
+ *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
+#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
+
+static void *
+xmalloc (size_t n)
+{
+ char *p = malloc (n);
+ if (!p)
+ {
+ fputs ("\nfatal: out of core\n", stderr);
+ exit (4);
+ }
+ return p;
+}
+
+/* Please: Don't call an allocation function xfoo when it may return NULL. */
+/* Wrong: #define xstrdup( x ) (x)?strdup(x):0 */
+/* Right: */
+static char *
+xstrdup (const char *string)
+{
+ char *p = xmalloc (strlen (string)+1);
+ strcpy (p, string);
+ return p;
+}
+
+
+
+bool initialize()
+{
+ config.bugURL = malloc( strlen( BUG_URL ) + 1 );
+ strcpy( (char* )config.bugURL, BUG_URL );
+ config.signatureKeyCertificate = malloc( 1 );
+ strcpy( (char* )config.signatureKeyCertificate, "" );
+ config.signatureAlgorithm = SignAlg_SHA1;
+ if( GPGMEPLUG_PROTOCOL == GPGME_PROTOCOL_CMS )
+ config.signatureCompoundMode = SignatureCompoundMode_Opaque;
+ else
+ config.signatureCompoundMode = SignatureCompoundMode_Detached;
+ config.sendCertificates = SendCert_SendChainWithRoot;
+ config.signEmail = SignEmail_SignAll;
+ config.saveSentSignatures = true;
+ config.warnNoCertificate = true;
+ config.numPINRequests = PinRequest_Always;
+ config.checkSignatureCertificatePathToRoot = true;
+ config.signatureUseCRLs = true;
+ config.encryptionAlgorithm = EncryptAlg_RSA;
+ config.encryptEmail = EncryptEmail_Ask;
+ config.saveMessagesEncrypted = true;
+ config.checkEncryptionCertificatePathToRoot = true;
+ config.encryptionUseCRLs = true;
+ config.encryptionCRLExpiryNearWarning = true;
+ config.encryptionCRLNearExpiryInterval = NEAR_EXPIRY;
+ config.directoryServers = NULL;
+ config.numDirectoryServers = 0;
+ config.certificateSource = CertSrc_Server;
+ config.cRLSource = CertSrc_Server;
+ config.warnSendUnsigned = true;
+ config.numPINRequestsInterval = NEAR_EXPIRY;
+ config.signatureCertificateExpiryNearWarning = true;
+ config.signatureCertificateExpiryNearInterval = NEAR_EXPIRY;
+ config.cACertificateExpiryNearWarning = true;
+ config.cACertificateExpiryNearInterval = NEAR_EXPIRY;
+ config.rootCertificateExpiryNearWarning = true;
+ config.rootCertificateExpiryNearInterval = NEAR_EXPIRY;
+ config.warnSendUnencrypted = false;
+ config.checkCertificatePath = true;
+ config.receiverCertificateExpiryNearWarning = true;
+ config.receiverCertificateExpiryNearWarningInterval = NEAR_EXPIRY;
+ config.certificateInChainExpiryNearWarning = true;
+ config.certificateInChainExpiryNearWarningInterval = NEAR_EXPIRY;
+ config.receiverEmailAddressNotInCertificateWarning = true;
+ config.libVersion = gpgme_check_version (NULL);
+ return (gpgme_engine_check_version (GPGMEPLUG_PROTOCOL) == GPGME_No_Error);
+};
+
+
+void deinitialize()
+{
+ unsigned int i;
+ for( i = 0; i < config.numDirectoryServers; ++i ) {
+ free( (char *)config.directoryServers[i].servername );
+ free( (char *)config.directoryServers[i].description );
+ }
+ free( config.directoryServers );
+}
+
+
+bool hasFeature( Feature flag )
+{
+ /* our own plugins are supposed to support everything */
+ switch ( flag ) {
+ case Feature_SignMessages: return true;
+ case Feature_VerifySignatures: return true;
+ case Feature_EncryptMessages: return true;
+ case Feature_DecryptMessages: return true;
+ case Feature_SendCertificates: return true;
+ case Feature_WarnSignCertificateExpiry: return true;
+ case Feature_WarnSignEmailNotInCertificate: return true;
+ case Feature_PinEntrySettings: return true;
+ case Feature_StoreMessagesWithSigs: return true;
+ case Feature_EncryptionCRLs: return true;
+ case Feature_WarnEncryptCertificateExpiry: return true;
+ case Feature_WarnEncryptEmailNotInCertificate: return true;
+ case Feature_StoreMessagesEncrypted: return true;
+ case Feature_CheckCertificatePath: return true;
+ case Feature_CertificateDirectoryService: return false;
+ case Feature_CRLDirectoryService: return false;
+ /* undefined or not yet implemented: */
+ case Feature_undef: return false;
+ default: return false;
+ }
+}
+
+
+const char* libVersion(){ return config.libVersion; }
+
+
+const char* bugURL(){ return config.bugURL; }
+
+
+void unsafeStationery( void** pixmap, const char** menutext, char* accel,
+ const char** tooltip, const char** statusbartext ){}
+
+void signedStationery( void** pixmap, const char** menutext, char* accel,
+ const char** tooltip, const char** statusbartext ){}
+
+void encryptedStationery( void** pixmap, const char**
+ menutext, char* accel,
+ const char** tooltip, const char** statusbartext ){}
+
+void signedEncryptedStationery( void** pixmap, const char**
+ menutext, char* accel,
+ const char** tooltip, const char** statusbartext ){}
+
+const char* signatureConfigurationDialog(){ return 0; }
+
+const char* signatureKeySelectionDialog(){ return 0; }
+
+const char* signatureAlgorithmDialog(){ return 0; }
+
+const char* signatureHandlingDialog(){ return 0; }
+
+void setSignatureKeyCertificate( const char* certificate )
+{
+ config.signatureKeyCertificate = certificate;
+}
+
+const char* signatureKeyCertificate()
+{
+ return config.signatureKeyCertificate;
+}
+
+void setSignatureAlgorithm( SignatureAlgorithm sigAlg )
+{
+ config.signatureAlgorithm = sigAlg;
+}
+
+SignatureAlgorithm signatureAlgorithm()
+{
+ return config.signatureAlgorithm;
+}
+
+void setSignatureCompoundMode( SignatureCompoundMode signComp )
+{
+ config.signatureCompoundMode = signComp;
+}
+
+SignatureCompoundMode signatureCompoundMode()
+{
+ return config.signatureCompoundMode;
+}
+
+void setSendCertificates( SendCertificates sendCert )
+{
+ config.sendCertificates = sendCert;
+}
+
+SendCertificates sendCertificates()
+{
+ return config.sendCertificates;
+}
+
+void setSignEmail( SignEmail signMail )
+{
+ config.signEmail = signMail;
+}
+
+SignEmail signEmail()
+{
+ return config.signEmail;
+}
+
+
+
+
+
+void setWarnSendUnsigned( bool flag )
+{
+ config.warnSendUnsigned = flag;
+}
+
+bool warnSendUnsigned()
+{
+ return config.warnSendUnsigned;
+}
+
+
+
+
+
+
+void setSaveSentSignatures( bool flag )
+{
+ config.saveSentSignatures = flag;
+}
+
+bool saveSentSignatures()
+{
+ return config.saveSentSignatures;
+}
+
+void setWarnNoCertificate( bool flag )
+{
+ config.warnNoCertificate = flag;
+}
+
+bool warnNoCertificate()
+{
+ return config.warnNoCertificate;
+}
+
+
+bool isEmailInCertificate( const char* email, const char* certificate )
+{
+ /* PENDING(g10) this function should return true if the email
+ address passed as the first parameter is contained in the
+ certificate passed as the second parameter, and false
+ otherwise. This is used to alert the user if his own email
+ address is not contained in the certificate he uses for
+ signing.
+ Note that the parameter email can be anything that is allowed
+ in a From: line.
+ Another note: OK, OK, we'll handle that in the MUA. You can
+ assume that you only get the email address.
+ */
+ return false; /* dummy*/
+}
+
+
+void setNumPINRequests( PinRequests reqMode )
+{
+ config.numPINRequests = reqMode;
+
+ /* PENDING(g10) Put this value into gpg and make it ask for the pin
+ according to this. Note that there is also
+ setNumPINRequestsInterval() which is only used if reqMode ==
+ PinRequest_AfterMinutes.
+ */
+}
+
+PinRequests numPINRequests()
+{
+ return config.numPINRequests;
+}
+
+
+
+void setNumPINRequestsInterval( int interval )
+{
+ config.numPINRequestsInterval = interval;
+
+ /* PENDING(g10) Put this value into gpg and make it ask for the pin
+ according to this. Note that this should only be used if
+ config.numPINRequests (set with setNumPINRequests()) has the
+ value PinRequest_AfterMinutes.
+ */
+}
+
+int numPINRequestsInterval()
+{
+ return config.numPINRequestsInterval;
+}
+
+
+
+void setCheckSignatureCertificatePathToRoot( bool flag )
+{
+ config.checkSignatureCertificatePathToRoot = flag;
+}
+
+bool checkSignatureCertificatePathToRoot()
+{
+ return config.checkSignatureCertificatePathToRoot;
+}
+
+void setSignatureUseCRLs( bool flag )
+{
+ config.signatureUseCRLs = flag;
+}
+
+bool signatureUseCRLs()
+{
+ return config.signatureUseCRLs;
+}
+
+
+
+
+
+
+void setSignatureCertificateExpiryNearWarning( bool flag )
+{
+ config.signatureCertificateExpiryNearWarning = flag;
+}
+
+bool signatureCertificateExpiryNearWarning( void )
+{
+ return config.signatureCertificateExpiryNearWarning;
+}
+
+
+int signatureCertificateDaysLeftToExpiry( const char* certificate )
+{
+ GpgmeCtx ctx;
+ GpgmeError err;
+ GpgmeKey rKey;
+ int daysLeft = CRYPTPLUG_CERT_DOES_NEVER_EXPIRE;
+
+ gpgme_new( &ctx );
+ gpgme_set_protocol( ctx, GPGMEPLUG_PROTOCOL );
+
+ err = gpgme_op_keylist_start( ctx, certificate, 0 );
+ if ( GPGME_No_Error == err ) {
+ err = gpgme_op_keylist_next( ctx, &rKey );
+ gpgme_op_keylist_end( ctx );
+ if ( GPGME_No_Error == err ) {
+ time_t expire_time = gpgme_key_get_ulong_attr(
+ rKey, GPGME_ATTR_EXPIRE, NULL, 0 );
+ if ( 0 != expire_time ) {
+ time_t cur_time = time (NULL);
+ if( cur_time > expire_time ) {
+ daysLeft = days_from_seconds(cur_time - expire_time);
+ daysLeft *= -1;
+ }
+ else
+ daysLeft = days_from_seconds(expire_time - cur_time);
+ }
+ gpgme_key_release( rKey );
+ }
+ }
+ gpgme_release( ctx );
+
+ /*
+ fprintf( stderr, "gpgmeplug signatureCertificateDaysLeftToExpiry returned %d\n", daysLeft );
+ */
+
+ return daysLeft;
+}
+
+
+void setSignatureCertificateExpiryNearInterval( int interval )
+{
+ config.signatureCertificateExpiryNearInterval = interval;
+}
+
+int signatureCertificateExpiryNearInterval( void )
+{
+ return config.signatureCertificateExpiryNearInterval;
+}
+
+void setCACertificateExpiryNearWarning( bool flag )
+{
+ config.cACertificateExpiryNearWarning = flag;
+}
+
+bool caCertificateExpiryNearWarning( void )
+{
+ return config.cACertificateExpiryNearWarning;
+}
+
+int caCertificateDaysLeftToExpiry( const char* certificate )
+{
+ /* PENDING(g10)
+ Please return the number of days that are left until the
+ CA certificate for the certificate specified in the parameter
+ certificate expires.
+ */
+ /*
+ GpgmeCtx ctx;
+ GpgmeError err;
+ GpgmeKey rKey;
+ time_t daysLeft = 0;
+
+ gpgme_new( &ctx );
+ gpgme_set_protocol( ctx, GPGMEPLUG_PROTOCOL );
+
+ err = gpgme_op_keylist_start( ctx, certificate, 0 );
+ if ( GPGME_No_Error == err ) {
+ err = gpgme_op_keylist_next( ctx, &rKey );
+ gpgme_op_keylist_end( ctx );
+ if ( GPGME_No_Error == err ) {
+ time_t expire_time = gpgme_key_get_ulong_attr(
+ rKey,
+
+??????????????????????? GPGME_ATTR_EXPIRE, ???????????????????????
+
+ NULL, 0 );
+ time_t cur_time = time (NULL);
+ daysLeft = days_from_seconds(expire_time - cur_time);
+ gpgme_key_release( rKey );
+ }
+ }
+ gpgme_release( ctx );
+
+
+ // fprintf( stderr, "gpgmeplug caCertificateDaysLeftToExpiry returned %d\n", daysLeft );
+ return daysLeft;
+ */
+
+ return 10; /* dummy that triggers a warning in the MUA */
+}
+
+void setCACertificateExpiryNearInterval( int interval )
+{
+ config.cACertificateExpiryNearInterval = interval;
+}
+
+int caCertificateExpiryNearInterval( void )
+{
+ return config.cACertificateExpiryNearInterval;
+}
+
+void setRootCertificateExpiryNearWarning( bool flag )
+{
+ config.rootCertificateExpiryNearWarning = flag;
+}
+
+bool rootCertificateExpiryNearWarning( void )
+{
+ return config.rootCertificateExpiryNearWarning;
+}
+
+int rootCertificateDaysLeftToExpiry( const char* certificate )
+{
+ /* PENDING(g10)
+ Please return the number of days that are left until the
+ root certificate for the certificate specified in the parameter
+ certificate expires.
+ */
+ /*
+ GpgmeCtx ctx;
+ GpgmeError err;
+ GpgmeKey rKey;
+ time_t daysLeft = 0;
+
+ gpgme_new( &ctx );
+ gpgme_set_protocol( ctx, GPGMEPLUG_PROTOCOL );
+
+ err = gpgme_op_keylist_start( ctx, certificate, 0 );
+ if ( GPGME_No_Error == err ) {
+ err = gpgme_op_keylist_next( ctx, &rKey );
+ gpgme_op_keylist_end( ctx );
+ if ( GPGME_No_Error == err ) {
+ time_t expire_time = gpgme_key_get_ulong_attr(
+ rKey,
+
+??????????????????????? GPGME_ATTR_EXPIRE, ???????????????????????
+
+ NULL, 0 );
+ time_t cur_time = time (NULL);
+ daysLeft = days_from_seconds(expire_time - cur_time);
+ gpgme_key_release( rKey );
+ }
+ }
+ gpgme_release( ctx );
+
+
+ // fprintf( stderr, "gpgmeplug rootCertificateDaysLeftToExpiry returned %d\n", daysLeft );
+ return daysLeft;
+ */
+
+ return 10; /* dummy that triggers a warning in the MUA */
+}
+
+
+void setRootCertificateExpiryNearInterval( int interval )
+{
+ config.rootCertificateExpiryNearInterval = interval;
+}
+
+int rootCertificateExpiryNearInterval( void )
+{
+ return config.rootCertificateExpiryNearInterval;
+}
+
+
+
+
+
+
+
+
+const char* encryptionConfigurationDialog(){ return 0; }
+
+const char* encryptionAlgorithmDialog(){ return 0; }
+
+const char* encryptionHandlingDialog(){ return 0; }
+
+const char* encryptionReceiverDialog(){ return 0; }
+
+void setEncryptionAlgorithm( EncryptionAlgorithm cryptAlg )
+{
+ config.encryptionAlgorithm = cryptAlg;
+}
+
+EncryptionAlgorithm encryptionAlgorithm()
+{
+ return config.encryptionAlgorithm;
+}
+
+void setEncryptEmail( EncryptEmail cryptMode )
+{
+ config.encryptEmail = cryptMode;
+}
+
+EncryptEmail encryptEmail()
+{
+ return config.encryptEmail;
+}
+
+
+
+
+
+
+void setWarnSendUnencrypted( bool flag )
+{
+ config.warnSendUnencrypted = flag;
+}
+
+bool warnSendUnencrypted()
+{
+ return config.warnSendUnencrypted;
+}
+
+
+
+
+
+
+
+
+
+void setSaveMessagesEncrypted( bool flag )
+{
+ config.saveMessagesEncrypted = flag;
+}
+
+bool saveMessagesEncrypted()
+{
+ return config.saveMessagesEncrypted;
+}
+
+
+
+
+
+
+
+void setCheckCertificatePath( bool flag )
+{
+ config.checkCertificatePath = flag;
+}
+
+bool checkCertificatePath()
+{
+ return config.checkCertificatePath;
+}
+
+
+
+
+
+
+
+
+void setCheckEncryptionCertificatePathToRoot( bool flag )
+{
+ config.checkEncryptionCertificatePathToRoot = flag;
+}
+
+bool checkEncryptionCertificatePathToRoot()
+{
+ return config.checkEncryptionCertificatePathToRoot;
+}
+
+
+
+
+
+
+
+void setReceiverCertificateExpiryNearWarning( bool flag )
+{
+ config.receiverCertificateExpiryNearWarning = flag;
+}
+
+bool receiverCertificateExpiryNearWarning()
+{
+ return config.receiverCertificateExpiryNearWarning;
+}
+
+
+int receiverCertificateDaysLeftToExpiry( const char* certificate )
+{
+ GpgmeCtx ctx;
+ GpgmeError err;
+ GpgmeKey rKey;
+ int daysLeft = CRYPTPLUG_CERT_DOES_NEVER_EXPIRE;
+
+ gpgme_new( &ctx );
+ gpgme_set_protocol( ctx, GPGMEPLUG_PROTOCOL );
+
+ err = gpgme_op_keylist_start( ctx, certificate, 0 );
+ if ( GPGME_No_Error == err ) {
+ err = gpgme_op_keylist_next( ctx, &rKey );
+ gpgme_op_keylist_end( ctx );
+ if ( GPGME_No_Error == err ) {
+ time_t expire_time = gpgme_key_get_ulong_attr(
+ rKey,GPGME_ATTR_EXPIRE, NULL, 0 );
+ if ( 0 != expire_time ) {
+ time_t cur_time = time (NULL);
+ if( cur_time > expire_time ) {
+ daysLeft = days_from_seconds(cur_time - expire_time);
+ daysLeft *= -1;
+ }
+ else
+ daysLeft = days_from_seconds(expire_time - cur_time);
+ }
+ gpgme_key_release( rKey );
+ }
+ }
+ gpgme_release( ctx );
+
+ /*
+ fprintf( stderr, "gpgmeplug receiverCertificateDaysLeftToExpiry returned %d\n", daysLeft );
+ */
+
+ return daysLeft;
+}
+
+
+void setReceiverCertificateExpiryNearWarningInterval( int interval )
+{
+ config.receiverCertificateExpiryNearWarningInterval = interval;
+}
+
+int receiverCertificateExpiryNearWarningInterval()
+{
+ return config.receiverCertificateExpiryNearWarningInterval;
+}
+
+void setCertificateInChainExpiryNearWarning( bool flag )
+{
+ config.certificateInChainExpiryNearWarning = flag;
+}
+
+bool certificateInChainExpiryNearWarning()
+{
+ return config.certificateInChainExpiryNearWarning;
+}
+
+
+int certificateInChainDaysLeftToExpiry( const char* certificate )
+{
+ /* PENDING(g10)
+ Please return the number of days that are left until the
+ the first certificate in the chain of the specified certificate
+ expires.
+ */
+ return 10; /* dummy that triggers a warning in the MUA */
+}
+
+
+void setCertificateInChainExpiryNearWarningInterval( int interval )
+{
+ config.certificateInChainExpiryNearWarningInterval = interval;
+}
+
+int certificateInChainExpiryNearWarningInterval()
+{
+ return config.certificateInChainExpiryNearWarningInterval;
+}
+
+void setReceiverEmailAddressNotInCertificateWarning( bool flag )
+{
+ config.receiverEmailAddressNotInCertificateWarning = flag;
+}
+
+bool receiverEmailAddressNotInCertificateWarning()
+{
+ return config.receiverEmailAddressNotInCertificateWarning;
+}
+
+
+
+
+
+
+
+
+void setEncryptionUseCRLs( bool flag )
+{
+ config.encryptionUseCRLs = flag;
+
+ /* PENDING(g10) Store this setting in gpgme and use it. If true,
+ every certificate used for encryption should be checked against
+ applicable CRLs.
+ */
+}
+
+bool encryptionUseCRLs()
+{
+ return config.encryptionUseCRLs;
+}
+
+
+int encryptionCRLsDaysLeftToExpiry()
+{
+ /* PENDING(g10)
+ Please return the number of days that are left until the
+ CRL used for encryption expires.
+ */
+ return 10; /* dummy that triggers a warning in the MUA */
+}
+
+void setEncryptionCRLExpiryNearWarning( bool flag )
+{
+ config.encryptionCRLExpiryNearWarning = flag;
+}
+
+bool encryptionCRLExpiryNearWarning()
+{
+ return config.encryptionCRLExpiryNearWarning;
+}
+
+void setEncryptionCRLNearExpiryInterval( int interval )
+{
+ config.encryptionCRLNearExpiryInterval = interval;
+}
+
+int encryptionCRLNearExpiryInterval()
+{
+ return config.encryptionCRLNearExpiryInterval;
+}
+
+
+const char* directoryServiceConfigurationDialog(){ return 0; }
+
+void appendDirectoryServer( const char* servername,
+ int port,
+ const char* description )
+{
+ struct DirectoryServer *newServers = NULL;
+ newServers = realloc( config.directoryServers,
+ (1+config.numDirectoryServers) * sizeof *newServers );
+ if( newServers ) {
+ config.directoryServers = newServers;
+ newServers[ config.numDirectoryServers ].servername =
+ malloc( 1+strlen( servername ) );
+ if( newServers[ config.numDirectoryServers ].servername ) {
+ strcpy( (char *)newServers[ config.numDirectoryServers ].servername,
+ servername );
+ newServers[ config.numDirectoryServers ].description =
+ malloc( 1+strlen( description ) );
+ if( newServers[ config.numDirectoryServers ].description ) {
+ strcpy( (char *)newServers[ config.numDirectoryServers ].description,
+ description );
+ newServers[ config.numDirectoryServers ].port = port;
+ config.numDirectoryServers += 1;
+ }
+ }
+ }
+}
+
+void setDirectoryServers( struct DirectoryServer server[], unsigned int size )
+{
+ unsigned int i;
+ int oldSize = config.numDirectoryServers;
+ struct DirectoryServer *newServers = NULL;
+ newServers = calloc ( size, sizeof *newServers );
+ if( newServers ) {
+ for( i=0; i < oldSize; ++i ) {
+ free( (char *)config.directoryServers[i].servername );
+ free( (char *)config.directoryServers[i].description );
+ }
+ free( config.directoryServers );
+ for( i=0; i < size; ++i ) {
+ newServers[ i ].servername = malloc( 1+strlen( server[i].servername ) );
+ if( newServers[ i ].servername ) {
+ strcpy( (char *)newServers[ i ].servername, server[i].servername );
+ newServers[ i ].description = malloc( 1+strlen( server[i].description ) );
+ if( newServers[ i ].description ) {
+ strcpy( (char *)newServers[ i ].description, server[i].description );
+ newServers[ i ].port = server[i].port;
+ }
+ }
+ }
+ config.directoryServers = newServers;
+ config.numDirectoryServers = size;
+ }
+}
+
+struct DirectoryServer * directoryServers( int* numServers )
+{
+ if( numServers )
+ *numServers = config.numDirectoryServers;
+ return config.directoryServers;
+};
+
+void setCertificateSource( CertificateSource source )
+{
+ config.certificateSource = source;
+}
+
+CertificateSource certificateSource()
+{
+ return config.certificateSource;
+}
+
+void setCRLSource( CertificateSource source )
+{
+ config.cRLSource = source;
+}
+
+CertificateSource crlSource()
+{
+ return config.cRLSource;
+}
+
+
+bool certificateValidity( const char* certificate,
+ int* level ){ return true; }
+
+
+void storeNewCharPtr( char** dest, const char* src )
+{
+ int sLen = strlen( src );
+ *dest = xmalloc( sLen + 1 );
+ strcpy( *dest, src );
+}
+
+
+bool signMessage( const char* cleartext,
+ char** ciphertext,
+ const size_t* cipherLen,
+ const char* certificate,
+ struct StructuringInfo* structuring,
+ int* errId,
+ char** errTxt )
+{
+ bool bIsOpaque;
+ GpgmeCtx ctx;
+ GpgmeError err;
+ GpgmeKey rKey;
+ GpgmeData data, sig;
+ char* rSig = 0;
+ bool bOk = false;
+ int sendCerts = 1;
+
+ init_StructuringInfo( structuring );
+
+ if( !ciphertext )
+ return false;
+
+ err = gpgme_new (&ctx);
+ gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
+
+ gpgme_set_armor (ctx, __GPGMEPLUG_SIGNATURE_CODE_IS_BINARY ? 0 : 1);
+ /* gpgme_set_textmode (ctx, 1); */
+
+ switch ( config.sendCertificates ) {
+ case SendCert_undef:
+ break;
+ case SendCert_DontSend:
+ sendCerts = 0;
+ break;
+ case SendCert_SendOwn:
+ sendCerts = 1;
+ break;
+ case SendCert_SendChainWithoutRoot:
+ sendCerts = -2;
+ break;
+ case SendCert_SendChainWithRoot:
+ sendCerts = -1;
+ break;
+ default:
+ sendCerts = 0;
+ break;
+ }
+ gpgme_set_include_certs (ctx, sendCerts);
+
+ /* select the signer's key if provided */
+ if (certificate != 0) {
+ err = gpgme_op_keylist_start(ctx, certificate, 0);
+ while (err == GPGME_No_Error) {
+ err = gpgme_op_keylist_next(ctx, &rKey);
+ if (err == GPGME_No_Error) {
+ unsigned long u;
+ u = gpgme_key_get_ulong_attr(rKey, GPGME_ATTR_CAN_SIGN, 0, 0);
+ if( u ) {
+
+// const char* s;
+// s = gpgme_key_get_string_attr(rKey, GPGME_ATTR_FPR, 0, 0);
+// fprintf( stderr, "gpgmeplug signMessage signing with key: %s\n", s );
+
+ /* clear existing signers */
+ gpgme_signers_clear(ctx);
+ /* set the signing key */
+ gpgme_signers_add(ctx, rKey);
+ /* we only support one signer for now */
+ break;
+ }
+ }
+ }
+ gpgme_op_keylist_end(ctx);
+ }
+
+ /* PENDING(g10) Implement this
+
+ gpgme_set_signature_algorithm( ctx, config.signatureAlgorithm )
+ --> This does not make sense. The algorithm is a property of
+ the certificate used [wk 2002-03-23] */
+
+ gpgme_data_new_from_mem (&data, cleartext,
+ strlen( cleartext ), 1 );
+ gpgme_data_new ( &sig );
+
+ /* NOTE: Currently we support Opaque signed messages only for S/MIME,
+ but not for OpenPGP mode! */
+ if( GPGMEPLUG_PROTOCOL == GPGME_PROTOCOL_CMS )
+ bIsOpaque = (SignatureCompoundMode_Opaque == signatureCompoundMode());
+ else
+ bIsOpaque = false;
+
+ err = gpgme_op_sign ( ctx,
+ data,
+ sig,
+ bIsOpaque
+ ? GPGME_SIG_MODE_NORMAL
+ : GPGME_SIG_MODE_DETACH );
+
+ if ( err == GPGME_No_Error ) {
+ if( __GPGMEPLUG_SIGNATURE_CODE_IS_BINARY ) {
+ *ciphertext = gpgme_data_release_and_get_mem( sig, (size_t*)cipherLen );
+ bOk = true;
+ }
+ else {
+ rSig = gpgme_data_release_and_get_mem( sig, (size_t*)cipherLen );
+ *ciphertext = malloc( *cipherLen + 1 );
+ if( *ciphertext ) {
+ if( *cipherLen ) {
+ bOk = true;
+ strncpy((char*)*ciphertext, rSig, *cipherLen );
+ }
+ (*ciphertext)[*cipherLen] = '\0';
+ }
+ free( rSig );
+ }
+ }
+ else {
+ gpgme_data_release( sig );
+/*
+*ciphertext = malloc( 70 );
+strcpy((char*)*ciphertext, "xyz\nsig-dummy\nzyx" );
+(*ciphertext)[17] = '\0';
+err = 0;
+{
+*/
+ *ciphertext = 0;
+ fprintf( stderr, "\n\n gpgme_op_sign() returned this error code: %i\n\n", err );
+ if( errId )
+ *errId = err;
+ if( errTxt ) {
+ const char* _errTxt = gpgme_strerror( err );
+ *errTxt = malloc( strlen( _errTxt ) + 1 );
+ if( *errTxt )
+ strcpy(*errTxt, _errTxt );
+ }
+/*
+}
+*/
+ }
+ gpgme_data_release( data );
+ gpgme_release (ctx);
+
+ if( bOk && structuring ) {
+ if( bIsOpaque ) {
+ structuring->includeCleartext = GPGMEPLUG_OPA_SIGN_INCLUDE_CLEARTEXT;
+ structuring->makeMimeObject = GPGMEPLUG_OPA_SIGN_MAKE_MIME_OBJECT;
+ if( structuring->makeMimeObject ) {
+ structuring->makeMultiMime = GPGMEPLUG_OPA_SIGN_MAKE_MULTI_MIME;
+ storeNewCharPtr( &structuring->contentTypeMain,
+ GPGMEPLUG_OPA_SIGN_CTYPE_MAIN );
+ storeNewCharPtr( &structuring->contentDispMain,
+ GPGMEPLUG_OPA_SIGN_CDISP_MAIN );
+ storeNewCharPtr( &structuring->contentTEncMain,
+ GPGMEPLUG_OPA_SIGN_CTENC_MAIN );
+ if( structuring->makeMultiMime ) {
+ storeNewCharPtr( &structuring->contentTypeVersion,
+ GPGMEPLUG_OPA_SIGN_CTYPE_VERSION );
+ storeNewCharPtr( &structuring->contentDispVersion,
+ GPGMEPLUG_OPA_SIGN_CDISP_VERSION );
+ storeNewCharPtr( &structuring->contentTEncVersion,
+ GPGMEPLUG_OPA_SIGN_CTENC_VERSION );
+ storeNewCharPtr( &structuring->bodyTextVersion,
+ GPGMEPLUG_OPA_SIGN_BTEXT_VERSION );
+ storeNewCharPtr( &structuring->contentTypeCode,
+ GPGMEPLUG_OPA_SIGN_CTYPE_CODE );
+ storeNewCharPtr( &structuring->contentDispCode,
+ GPGMEPLUG_OPA_SIGN_CDISP_CODE );
+ storeNewCharPtr( &structuring->contentTEncCode,
+ GPGMEPLUG_OPA_SIGN_CTENC_CODE );
+ }
+ } else {
+ storeNewCharPtr( &structuring->flatTextPrefix,
+ GPGMEPLUG_OPA_SIGN_FLAT_PREFIX );
+ storeNewCharPtr( &structuring->flatTextSeparator,
+ GPGMEPLUG_OPA_SIGN_FLAT_SEPARATOR );
+ storeNewCharPtr( &structuring->flatTextPostfix,
+ GPGMEPLUG_OPA_SIGN_FLAT_POSTFIX );
+ }
+ } else {
+ structuring->includeCleartext = GPGMEPLUG_DET_SIGN_INCLUDE_CLEARTEXT;
+ structuring->makeMimeObject = GPGMEPLUG_DET_SIGN_MAKE_MIME_OBJECT;
+ if( structuring->makeMimeObject ) {
+ structuring->makeMultiMime = GPGMEPLUG_DET_SIGN_MAKE_MULTI_MIME;
+ storeNewCharPtr( &structuring->contentTypeMain,
+ GPGMEPLUG_DET_SIGN_CTYPE_MAIN );
+ storeNewCharPtr( &structuring->contentDispMain,
+ GPGMEPLUG_DET_SIGN_CDISP_MAIN );
+ storeNewCharPtr( &structuring->contentTEncMain,
+ GPGMEPLUG_DET_SIGN_CTENC_MAIN );
+ if( structuring->makeMultiMime ) {
+ storeNewCharPtr( &structuring->contentTypeVersion,
+ GPGMEPLUG_DET_SIGN_CTYPE_VERSION );
+ storeNewCharPtr( &structuring->contentDispVersion,
+ GPGMEPLUG_DET_SIGN_CDISP_VERSION );
+ storeNewCharPtr( &structuring->contentTEncVersion,
+ GPGMEPLUG_DET_SIGN_CTENC_VERSION );
+ storeNewCharPtr( &structuring->bodyTextVersion,
+ GPGMEPLUG_DET_SIGN_BTEXT_VERSION );
+ storeNewCharPtr( &structuring->contentTypeCode,
+ GPGMEPLUG_DET_SIGN_CTYPE_CODE );
+ storeNewCharPtr( &structuring->contentDispCode,
+ GPGMEPLUG_DET_SIGN_CDISP_CODE );
+ storeNewCharPtr( &structuring->contentTEncCode,
+ GPGMEPLUG_DET_SIGN_CTENC_CODE );
+ }
+ } else {
+ storeNewCharPtr( &structuring->flatTextPrefix,
+ GPGMEPLUG_DET_SIGN_FLAT_PREFIX );
+ storeNewCharPtr( &structuring->flatTextSeparator,
+ GPGMEPLUG_DET_SIGN_FLAT_SEPARATOR );
+ storeNewCharPtr( &structuring->flatTextPostfix,
+ GPGMEPLUG_DET_SIGN_FLAT_POSTFIX );
+ }
+ }
+ }
+ return bOk;
+}
+
+
+
+bool storeCertificatesFromMessage(
+ const char* ciphertext ){ return true; }
+
+
+/* returns address if address doesn't contain a <xxx> part
+ * else it returns a new string xxx and frees address
+ */
+static char* parseAddress( char* address )
+{
+ char* result = address;
+ char* i;
+ char* j;
+ if( !result ) return result;
+ i = index( address, '<' );
+ if( i ) {
+ j = index( i+1, '>' );
+ if( j == NULL ) j = address+strlen(address);
+ result = xmalloc( j-i );
+ strncpy( result, i+1, j-i-1 );
+ result[j-i-1] = '\0';
+ free( address );
+ } else {
+ i = address;
+ j = i+strlen(address);
+ }
+ {
+ /* remove surrounding whitespace */
+ char* k = result+(j-i-1);
+ char* l = result;
+ while( isspace( *l ) ) ++l;
+ while( isspace( *k ) ) --k;
+ if( l != result || k != result+(j-i-1) ) {
+ char* result2 = xmalloc( k-l+2 );
+ strncpy( result2, l, k-l+1 );
+ result2[k-l+1] = '\0';
+ free(result);
+ result = result2;
+ }
+ }
+ return result;
+}
+
+static char* nextAddress( const char** address )
+{
+ const char *start = *address;
+ char* result = NULL;
+ int quote = 0;
+ int comment = 0;
+ int found = 0;
+ if( *address == NULL ) return NULL;
+ while( **address ) {
+
+ switch( **address ) {
+ case '\\': /* escaped character */
+ ++(*address);
+ break;
+ case '"':
+ if( comment == 0 ) {
+ if( quote > 0 ) --quote;
+ else ++quote;
+ }
+ break;
+ case '(': /* comment start */
+ if( quote == 0 ) ++comment;
+ break;
+ case ')': /* comment end */
+ if( quote == 0 ) --comment;
+ break;
+ case '\0':
+ case '\1': /* delimiter */
+ if( quote == 0 && comment == 0 ) {
+ found = 1;
+ }
+ break;
+ }
+ ++(*address);
+ if( found ) break;
+ }
+ if( found || **address == 0 ) {
+ size_t len;
+ len = *address - start;
+ if( len > 0 ) {
+ if( **address != 0 ) --len;
+ result = xmalloc( len*sizeof(char)+1 );
+ strncpy( result, start, len );
+ result[len] = '\0';
+ }
+ }
+ return parseAddress(result);
+}
+
+bool encryptMessage( const char* cleartext,
+ const char** ciphertext,
+ const size_t* cipherLen,
+ const char* certificate,
+ struct StructuringInfo* structuring,
+ int* errId,
+ char** errTxt )
+{
+ GpgmeCtx ctx;
+ GpgmeError err;
+ GpgmeData gCiphertext, gPlaintext;
+ GpgmeRecipients rset;
+ char* rCiph = 0;
+ bool bOk = false;
+
+ init_StructuringInfo( structuring );
+
+ gpgme_new (&ctx);
+ gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
+
+ gpgme_set_armor (ctx, __GPGMEPLUG_ENCRYPTED_CODE_IS_BINARY ? 0 : 1);
+ /* gpgme_set_textmode (ctx, 1); */
+
+ gpgme_data_new_from_mem (&gPlaintext, cleartext,
+ 1+strlen( cleartext ), 1 );
+ err = gpgme_data_new ( &gCiphertext );
+
+ gpgme_recipients_new (&rset);
+
+ /*
+ if( GPGMEPLUG_PROTOCOL == GPGME_PROTOCOL_CMS )
+ {
+ gpgme_recipients_add_name (rset,
+ "/CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=D�?sseldorf,C=DE" );
+
+ fputs( "\nGPGSMPLUG encryptMessage() using test key of Aegypten Project\n", stderr );
+ }
+ else
+ */
+ {
+ const char* p = certificate;
+ char* tok;
+ while( (tok = nextAddress( &p ) ) != 0 ) {
+ gpgme_recipients_add_name (rset, tok );
+ fprintf( stderr, "\nGPGMEPLUG encryptMessage() using addressee %s\n", tok );
+ free(tok);
+ }
+ }
+
+ /* PENDING(g10) Implement this
+ Possible values: RSA = 1, SHA1 = 2, TripleDES = 3
+ gpgme_set_encryption_algorithm( ctx, config.encryptionAlgorithm );
+
+ -> Your are mixing public key and symmetric algorithms. The
+ latter may be configured but the sphix specifications do opnly
+ allow 3-DES so this is not nothing we need to do. The proper way
+ to select the symmetric algorithm is anyway by looking at the
+ capabilities of the certificate because this is the only way to
+ know what the recipient can accept. [wk 2002-03-23]
+
+ PENDING(g10) Implement this
+ gpgme_set_encryption_check_certificate_path(
+ config.checkCertificatePath )
+
+ PENDING(g10) Implement this
+ gpgme_set_encryption_check_certificate_path_to_root(
+ config.checkEncryptionCertificatePathToRoot )
+
+ -> Not checking a certificate up to the ROOT CA is dangerous and
+ stupid. There is no need for those options. [wk 2002-03-23] */
+
+
+
+ err = gpgme_op_encrypt (ctx, rset, gPlaintext, gCiphertext );
+ if( err ) {
+ fprintf( stderr, "\ngpgme_op_encrypt() returned this error code: %i\n", err );
+ if( errId )
+ *errId = err;
+ if( errTxt ) {
+ const char* _errTxt = gpgme_strerror( err );
+ *errTxt = malloc( strlen( _errTxt ) + 100 ); // leave room for reason string
+ if( *errTxt ) {
+ char* opInfo;
+ strcpy(*errTxt, _errTxt );
+ opInfo = gpgme_get_op_info(ctx, 0);
+ if( NULL != opInfo && *opInfo ){
+ const int opLen = strlen( opInfo );
+ const int reasonLen = 8;
+ char reason[ 1+reasonLen ];
+ char* pos1;
+ strcpy( reason, "<reason>" );
+ pos1 = strstr( opInfo, reason );
+ if( NULL != pos1 &&
+ opLen > reasonLen + (pos1 - opInfo) ){
+ char* pos2;
+ pos1 += reasonLen;
+ pos2 = strchr( pos1, '<' );
+ if( NULL != pos2 &&
+ pos1 < pos2 ){
+ long int reasonId;
+ strcat( *errTxt, " - " );
+ *pos2 = '\0';
+ fprintf( stderr, " and this reason code: %s\n\n", pos1 );
+ reasonId = strtol( pos1, NULL, 10 );
+ switch( reasonId ) {
+ case 0: strcat( *errTxt, "No specific reason given" );
+ break;
+ case 1: strcat( *errTxt, "Not Found" );
+ break;
+ case 2: strcat( *errTxt, "Ambigious specification" );
+ break;
+ case 3: strcat( *errTxt, "Key can't be used for operation" );
+ break;
+ case 4: strcat( *errTxt, "Key has been revoked" );
+ break;
+ case 5: strcat( *errTxt, "Key has expired" );
+ break;
+ case 6: strcat( *errTxt, "No CRL known for certificate" );
+ break;
+ case 7: strcat( *errTxt, "No current CRL available" );
+ break;
+ case 8: strcat( *errTxt, "Contraints not matched" );
+ break;
+ default: {
+ strcat( *errTxt, "Extended error Id: #" );
+ strcat( *errTxt, pos1 );
+ }
+ }
+ *pos2 = '<';
+ }
+ }
+ free( opInfo );
+ }
+ }
+ }
+ }
+
+ gpgme_recipients_release (rset);
+ gpgme_data_release (gPlaintext);
+
+ if( err == GPGME_No_Error ) {
+ if( __GPGMEPLUG_ENCRYPTED_CODE_IS_BINARY ) {
+ *ciphertext = gpgme_data_release_and_get_mem( gCiphertext, (size_t*)cipherLen );
+ bOk = true;
+ }
+ else {
+ rCiph = gpgme_data_release_and_get_mem( gCiphertext, (size_t*)cipherLen );
+ *ciphertext = malloc( *cipherLen + 1 );
+ if( *ciphertext ) {
+ if( *cipherLen ) {
+ bOk = true;
+ strncpy((char*)*ciphertext, rCiph, *cipherLen );
+ }
+ ((char*)(*ciphertext))[*cipherLen] = 0;
+ }
+ free( rCiph );
+ }
+ }
+ else {
+ gpgme_data_release ( gCiphertext );
+ *ciphertext = 0;
+ /* error handling is missing: if only one untrusted key was found
+ (or none at all), gpg won't sign the message. (hier fehlt eine
+ Fehlerbehandlung: fuer einen Recipient nur ein untrusted key
+ (oder gar keiner) gefunden wurde, verweigert gpg das signieren.)
+ */
+ }
+
+ gpgme_release (ctx);
+
+ fflush( stderr );
+
+ if( bOk && structuring ) {
+ structuring->includeCleartext = GPGMEPLUG_ENC_INCLUDE_CLEARTEXT;
+ structuring->makeMimeObject = GPGMEPLUG_ENC_MAKE_MIME_OBJECT;
+ if( structuring->makeMimeObject ) {
+ structuring->makeMultiMime = GPGMEPLUG_ENC_MAKE_MULTI_MIME;
+ storeNewCharPtr( &structuring->contentTypeMain,
+ GPGMEPLUG_ENC_CTYPE_MAIN );
+ storeNewCharPtr( &structuring->contentDispMain,
+ GPGMEPLUG_ENC_CDISP_MAIN );
+ storeNewCharPtr( &structuring->contentTEncMain,
+ GPGMEPLUG_ENC_CTENC_MAIN );
+ if( structuring->makeMultiMime ) {
+ storeNewCharPtr( &structuring->contentTypeVersion,
+ GPGMEPLUG_ENC_CTYPE_VERSION );
+ storeNewCharPtr( &structuring->contentDispVersion,
+ GPGMEPLUG_ENC_CDISP_VERSION );
+ storeNewCharPtr( &structuring->contentTEncVersion,
+ GPGMEPLUG_ENC_CTENC_VERSION );
+ storeNewCharPtr( &structuring->bodyTextVersion,
+ GPGMEPLUG_ENC_BTEXT_VERSION );
+ storeNewCharPtr( &structuring->contentTypeCode,
+ GPGMEPLUG_ENC_CTYPE_CODE );
+ storeNewCharPtr( &structuring->contentDispCode,
+ GPGMEPLUG_ENC_CDISP_CODE );
+ storeNewCharPtr( &structuring->contentTEncCode,
+ GPGMEPLUG_ENC_CTENC_CODE );
+ }
+ } else {
+ storeNewCharPtr( &structuring->flatTextPrefix,
+ GPGMEPLUG_ENC_FLAT_PREFIX );
+ storeNewCharPtr( &structuring->flatTextSeparator,
+ GPGMEPLUG_ENC_FLAT_SEPARATOR );
+ storeNewCharPtr( &structuring->flatTextPostfix,
+ GPGMEPLUG_ENC_FLAT_POSTFIX );
+ }
+ }
+ return bOk;
+}
+
+
+bool encryptAndSignMessage( const char* cleartext,
+ const char** ciphertext,
+ const char* certificate,
+ struct StructuringInfo* structuring )
+{
+ bool bOk;
+
+ init_StructuringInfo( structuring );
+
+ bOk = false;
+
+ /* implementation of this function is still missing */
+
+ if( bOk && structuring ) {
+ structuring->includeCleartext = GPGMEPLUG_ENCSIGN_INCLUDE_CLEARTEXT;
+ structuring->makeMimeObject = GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT;
+ if( structuring->makeMimeObject ) {
+ structuring->makeMultiMime = GPGMEPLUG_ENCSIGN_MAKE_MULTI_MIME;
+ storeNewCharPtr( &structuring->contentTypeMain,
+ GPGMEPLUG_ENCSIGN_CTYPE_MAIN );
+ storeNewCharPtr( &structuring->contentDispMain,
+ GPGMEPLUG_ENCSIGN_CDISP_MAIN );
+ storeNewCharPtr( &structuring->contentTEncMain,
+ GPGMEPLUG_ENCSIGN_CTENC_MAIN );
+ if( structuring->makeMultiMime ) {
+ storeNewCharPtr( &structuring->contentTypeVersion,
+ GPGMEPLUG_ENCSIGN_CTYPE_VERSION );
+ storeNewCharPtr( &structuring->contentDispVersion,
+ GPGMEPLUG_ENCSIGN_CDISP_VERSION );
+ storeNewCharPtr( &structuring->contentTEncVersion,
+ GPGMEPLUG_ENCSIGN_CTENC_VERSION );
+ storeNewCharPtr( &structuring->bodyTextVersion,
+ GPGMEPLUG_ENCSIGN_BTEXT_VERSION );
+ storeNewCharPtr( &structuring->contentTypeCode,
+ GPGMEPLUG_ENCSIGN_CTYPE_CODE );
+ storeNewCharPtr( &structuring->contentDispCode,
+ GPGMEPLUG_ENCSIGN_CDISP_CODE );
+ storeNewCharPtr( &structuring->contentTEncCode,
+ GPGMEPLUG_ENCSIGN_CTENC_CODE );
+ }
+ } else {
+ storeNewCharPtr( &structuring->flatTextPrefix,
+ GPGMEPLUG_ENCSIGN_FLAT_PREFIX );
+ storeNewCharPtr( &structuring->flatTextSeparator,
+ GPGMEPLUG_ENCSIGN_FLAT_SEPARATOR );
+ storeNewCharPtr( &structuring->flatTextPostfix,
+ GPGMEPLUG_ENCSIGN_FLAT_POSTFIX );
+ }
+ }
+ return bOk;
+}
+
+
+bool decryptMessage( const char* ciphertext,
+ bool cipherIsBinary,
+ int cipherLen,
+ const char** cleartext,
+ const char* certificate,
+ int* errId,
+ char** errTxt )
+{
+ GpgmeCtx ctx;
+ GpgmeError err;
+ GpgmeData gCiphertext, gPlaintext;
+ size_t rCLen = 0;
+ char* rCiph = 0;
+ bool bOk = false;
+
+ if( !ciphertext )
+ return false;
+
+ err = gpgme_new (&ctx);
+ gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
+
+ gpgme_set_armor (ctx, cipherIsBinary ? 0 : 1);
+ /* gpgme_set_textmode (ctx, cipherIsBinary ? 0 : 1); */
+
+ /*
+ gpgme_data_new_from_mem( &gCiphertext, ciphertext,
+ 1+strlen( ciphertext ), 1 ); */
+ gpgme_data_new_from_mem( &gCiphertext,
+ ciphertext,
+ cipherIsBinary
+ ? cipherLen
+ : strlen( ciphertext ),
+ 1 );
+
+ gpgme_data_new( &gPlaintext );
+
+ err = err = gpgme_op_decrypt( ctx, gCiphertext, gPlaintext );
+ if( err ) {
+ fprintf( stderr, "\ngpgme_op_decrypt() returned this error code: %i\n\n", err );
+ if( errId )
+ *errId = err;
+ if( errTxt ) {
+ const char* _errTxt = gpgme_strerror( err );
+ *errTxt = malloc( strlen( _errTxt ) + 1 );
+ if( *errTxt )
+ strcpy(*errTxt, _errTxt );
+ }
+ }
+
+ gpgme_data_release( gCiphertext );
+
+ rCiph = gpgme_data_release_and_get_mem( gPlaintext, &rCLen );
+
+ *cleartext = malloc( rCLen + 1 );
+ if( *cleartext ) {
+ if( rCLen ) {
+ bOk = true;
+ strncpy((char*)*cleartext, rCiph, rCLen );
+ }
+ ((char*)(*cleartext))[rCLen] = 0;
+ }
+
+ free( rCiph );
+ gpgme_release( ctx );
+ return bOk;
+}
+
+
+const char* requestCertificateDialog(){ return 0; }
+
+
+/* The buffer generatedKey contains the LEN bytes you want.
+ Caller is responsible for freeing. */
+bool requestDecentralCertificate( const char* certparms,
+ char** generatedKey, int* length )
+{
+ GpgmeError err;
+ GpgmeCtx ctx;
+ GpgmeData pub;
+ int len;
+
+ err = gpgme_data_new (&pub);
+ fprintf( stderr, "1: gpgme returned %d\n", err );
+ if( err != GPGME_No_Error )
+ return false;
+
+ err = gpgme_new (&ctx);
+ fprintf( stderr, "2: gpgme returned %d\n", err );
+ if( err != GPGME_No_Error ) {
+ gpgme_data_release( pub );
+ return false;
+ }
+
+ gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
+ /* Don't ASCII-armor, the MUA will use base64 encoding */
+ /* gpgme_set_armor (ctx, 1); */
+ err = gpgme_op_genkey (ctx, certparms, pub, NULL );
+ fprintf( stderr, "3: gpgme returned %d\n", err );
+ if( err != GPGME_No_Error ) {
+ gpgme_data_release( pub );
+ gpgme_release( ctx );
+ return false;
+ }
+
+ gpgme_release (ctx);
+ *generatedKey = gpgme_data_release_and_get_mem (pub, &len);
+ *length = len;
+
+ return true;
+}
+
+bool requestCentralCertificateAndPSE( const char* name,
+ const char* email, const char* organization, const char* department,
+ const char* ca_address ){ return true; }
+
+bool createPSE(){ return true; }
+
+bool registerCertificate( const char* certificate ){ return true; }
+
+bool requestCertificateProlongation( const char* certificate,
+ const char* ca_address ){ return true; }
+
+const char* certificateChain(){ return 0; }
+
+bool deleteCertificate( const char* certificate ){ return true; }
+
+bool archiveCertificate( const char* certificate ){ return true; }
+
+
+const char* displayCRL(){ return 0; }
+
+void updateCRL(){}
+
+
+char *
+trim_trailing_spaces( char *string )
+{
+ char *p, *mark;
+
+ for( mark = NULL, p = string; *p; p++ ) {
+ if( isspace( *p ) ) {
+ if( !mark )
+ mark = p;
+ }
+ else
+ mark = NULL;
+ }
+ if( mark )
+ *mark = '\0' ;
+
+ return string ;
+}
+
+/* Parse a DN and return an array-ized one. This is not a validating
+ parser and it does not support any old-stylish syntax; gpgme is
+ expected to return only rfc2253 compatible strings. */
+static const unsigned char *
+parse_dn_part (struct DnPair *array, const unsigned char *string)
+{
+ const unsigned char *s, *s1;
+ size_t n;
+ unsigned char *p;
+
+ /* parse attributeType */
+ for (s = string+1; *s && *s != '='; s++)
+ ;
+ if (!*s)
+ return NULL; /* error */
+ n = s - string;
+ if (!n)
+ return NULL; /* empty key */
+ array->key = p = xmalloc (n+1);
+
+
+ memcpy (p, string, n);
+ p[n] = 0;
+ trim_trailing_spaces (p);
+ if ( !strcmp (p, "1.2.840.113549.1.9.1") )
+ strcpy (p, "EMail");
+ string = s + 1;
+
+ if (*string == '#')
+ { /* hexstring */
+ string++;
+ for (s=string; hexdigitp (s); s++)
+ s++;
+ n = s - string;
+ if (!n || (n & 1))
+ return NULL; /* empty or odd number of digits */
+ n /= 2;
+ array->value = p = xmalloc (n+1);
+
+
+ for (s1=string; n; s1 += 2, n--)
+ *p++ = xtoi_2 (s1);
+ *p = 0;
+ }
+ else
+ { /* regular v3 quoted string */
+ for (n=0, s=string; *s; s++)
+ {
+ if (*s == '\\')
+ { /* pair */
+ s++;
+ if (*s == ',' || *s == '=' || *s == '+'
+ || *s == '<' || *s == '>' || *s == '#' || *s == ';'
+ || *s == '\\' || *s == '\"' || *s == ' ')
+ n++;
+ else if (hexdigitp (s) && hexdigitp (s+1))
+ {
+ s++;
+ n++;
+ }
+ else
+ return NULL; /* invalid escape sequence */
+ }
+ else if (*s == '\"')
+ return NULL; /* invalid encoding */
+ else if (*s == ',' || *s == '=' || *s == '+'
+ || *s == '<' || *s == '>' || *s == '#' || *s == ';' )
+ break;
+ else
+ n++;
+ }
+
+ array->value = p = xmalloc (n+1);
+
+
+ for (s=string; n; s++, n--)
+ {
+ if (*s == '\\')
+ {
+ s++;
+ if (hexdigitp (s))
+ {
+ *p++ = xtoi_2 (s);
+ s++;
+ }
+ else
+ *p++ = *s;
+ }
+ else
+ *p++ = *s;
+ }
+ *p = 0;
+ }
+ return s;
+}
+
+
+/* Parse a DN and return an array-ized one. This is not a validating
+ parser and it does not support any old-stylish syntax; gpgme is
+ expected to return only rfc2253 compatible strings. */
+static struct DnPair *
+parse_dn (const unsigned char *string)
+{
+ struct DnPair *array;
+ size_t arrayidx, arraysize;
+ int i;
+
+ if( !string )
+ return NULL;
+
+ arraysize = 7; /* C,ST,L,O,OU,CN,email */
+ arrayidx = 0;
+ array = xmalloc ((arraysize+1) * sizeof *array);
+
+
+ while (*string)
+ {
+ while (*string == ' ')
+ string++;
+ if (!*string)
+ break; /* ready */
+ if (arrayidx >= arraysize)
+ { /* mutt lacks a real safe_realoc - so we need to copy */
+ struct DnPair *a2;
+
+ arraysize += 5;
+ a2 = xmalloc ((arraysize+1) * sizeof *array);
+ for (i=0; i < arrayidx; i++)
+ {
+ a2[i].key = array[i].key;
+ a2[i].value = array[i].value;
+ }
+ free (array);
+ array = a2;
+ }
+ array[arrayidx].key = NULL;
+ array[arrayidx].value = NULL;
+ string = parse_dn_part (array+arrayidx, string);
+ arrayidx++;
+ if (!string)
+ goto failure;
+ while (*string == ' ')
+ string++;
+ if (*string && *string != ',' && *string != ';' && *string != '+')
+ goto failure; /* invalid delimiter */
+ if (*string)
+ string++;
+ }
+ array[arrayidx].key = NULL;
+ array[arrayidx].value = NULL;
+ return array;
+
+ failure:
+ for (i=0; i < arrayidx; i++)
+ {
+ free (array[i].key);
+ free (array[i].value);
+ }
+ free (array);
+ return NULL;
+}
+
+static int
+add_dn_part( char* result, struct DnPair* dn, const char* part )
+{
+ int any = 0;
+
+ if( dn ) {
+ for(; dn->key; ++dn ) {
+ if( !strcmp( dn->key, part ) ) {
+ if( any ) strcat( result, "+" );
+ /* email hack */
+ if( !strcmp( part, "1.2.840.113549.1.9.1" ) ) strcat( result, "EMail" );
+ else strcat( result, part );
+ strcat( result, "=" );
+ strcat( result, dn->value );
+ any = 1;
+ }
+ }
+ }
+ return any;
+}
+
+static char*
+reorder_dn( struct DnPair *dn )
+{
+ /* note: The must parts are: CN, L, OU, O, C */
+ const char* stdpart[] = {
+ "CN", "S", "SN", "GN", "T", "UID",
+ "MAIL", "EMAIL", "MOBILE", "TEL", "FAX", "STREET",
+ "L", "PC", "SP", "ST",
+ "OU",
+ "O",
+ "C",
+ NULL
+ };
+ int any=0, any2=0, len=0, i;
+ char* result;
+ if( dn ) {
+ for( i = 0; dn[i].key; ++i ) {
+ len += strlen( dn[i].key );
+ len += strlen( dn[i].value );
+ len += 4; /* ',' and '=', and possibly "(" and ")" */
+ }
+ }
+ result = xmalloc( (len+1)*sizeof(char) );
+ *result = 0;
+
+ /* add standard parts */
+ for( i = 0; stdpart[i]; ++i ) {
+ if( any ) {
+ strcat( result, "," );
+ }
+ any = add_dn_part( result, dn, stdpart[i] );
+ }
+
+ /* add remaining parts in no particular order */
+ if( dn ) {
+ for(; dn->key; ++dn ) {
+ for( i = 0; stdpart[i]; ++i ) {
+ if( !strcmp( dn->key, stdpart[i] ) ) {
+ break;
+ }
+ }
+ if( !stdpart[i] ) {
+ if( any ) strcat( result, "," );
+ if( !any2 ) strcat( result, "(");
+ any = add_dn_part( result, dn, dn->key );
+ any2 = 1;
+ }
+ }
+ }
+ if( any2 ) strcat( result, ")");
+ return result;
+}
+
+struct CertIterator {
+ GpgmeCtx ctx;
+ struct CertificateInfo info;
+};
+
+struct CertIterator*
+startListCertificates( const char* pattern, int remote )
+{
+ GpgmeError err;
+ struct CertIterator* it;
+ const char* patterns[] = { pattern, NULL };
+ fprintf( stderr, "startListCertificates( \"%s\", %d )\n", pattern, remote );
+
+ it = xmalloc( sizeof( struct CertIterator ) );
+
+ err = gpgme_new (&(it->ctx));
+ /*fprintf( stderr, "2: gpgme returned %d\n", err );*/
+ if( err != GPGME_No_Error ) {
+ free( it );
+ return NULL;
+ }
+
+ gpgme_set_protocol (it->ctx, GPGME_PROTOCOL_CMS);
+ if( remote ) gpgme_set_keylist_mode ( it->ctx, GPGME_KEYLIST_MODE_EXTERN );
+ else gpgme_set_keylist_mode ( it->ctx, GPGME_KEYLIST_MODE_LOCAL );
+ err = gpgme_op_keylist_ext_start ( it->ctx, patterns, 0, 0);
+ if( err != GPGME_No_Error ) {
+ fprintf( stderr, "gpgme_op_keylist_ext_start returned %d", err );
+ endListCertificates( it );
+ return NULL;
+ }
+ memset( &(it->info), 0, sizeof( struct CertificateInfo ) );
+ return it;
+}
+
+/* free() each string in a char*[] and the array itself */
+static void
+freeStringArray( char** c )
+{
+ char** _c = c;
+
+ while( c && *c ) {
+ /*fprintf( stderr, "freeing \"%s\"\n", *c );*/
+ free( *c );
+ ++c;
+ }
+ free( _c );
+}
+
+/* free all malloc'ed data in a struct CertificateInfo */
+static void
+freeInfo( struct CertificateInfo* info )
+{
+ struct DnPair* a = info->dnarray;
+ assert( info );
+ freeStringArray( info->userid );
+ free( info->serial);
+ free( info->fingerprint );
+ free( info->issuer );
+ free( info->chainid );
+ free( info->caps );
+ while( a && a->key && a->value ) {
+ free (a->key);
+ free (a->value);
+ ++a;
+ }
+ free (info->dnarray);
+ memset( info, 0, sizeof( *info ) );
+}
+
+/* Format the fingerprint nicely. The caller should
+ free the returned value using free() */
+static char* make_fingerprint( const char* fpr )
+{
+ int len = strlen(fpr);
+ int i = 0;
+ char* result = xmalloc( (len + len/2 + 1)*sizeof(char) );
+
+ for(; *fpr; ++fpr, ++i ) {
+ if( i%3 == 2) {
+ result[i] = ':'; ++i;
+ }
+ result[i] = *fpr;
+ }
+ result[i] = 0;
+ return result;
+}
+
+int
+nextCertificate( struct CertIterator* it, struct CertificateInfo** result )
+{
+ GpgmeError err;
+ GpgmeKey key;
+ int retval = GPGME_No_Error;
+ assert( it );
+ fprintf( stderr, "nextCertificates( %p, %p )\n", it, result );
+ err = gpgme_op_keylist_next ( it->ctx, &key);
+ if( err != GPGME_EOF ) {
+ int idx;
+ const char* s;
+ unsigned long u;
+ char* names[MAX_GPGME_IDX+1];
+ struct DnPair *issuer_dn, *tmp_dn;
+ retval = err;
+ memset( names, 0, sizeof( names ) );
+ freeInfo( &(it->info) );
+
+ for( idx = 0; (s = gpgme_key_get_string_attr (key, GPGME_ATTR_USERID, 0, idx)) && idx < MAX_GPGME_IDX;
+ ++idx ) {
+ names[idx] = xstrdup( s );
+ }
+
+ it->info.userid = xmalloc( sizeof( char* ) * (idx+1) );
+ memset( it->info.userid, 0, sizeof( char* ) * (idx+1) );
+ it->info.dnarray = 0;
+ for( idx = 0; names[idx] != 0; ++idx ) {
+ struct DnPair* a = parse_dn( names[idx] );
+ if( idx == 0 ) {
+ it->info.userid[idx] = reorder_dn( a );
+ it->info.dnarray = a;
+ free (names[idx]);
+ names[idx] = NULL;
+ } else {
+ it->info.userid[idx] = names[idx];
+ }
+ }
+ it->info.userid[idx] = 0;
+
+ s = gpgme_key_get_string_attr (key, GPGME_ATTR_SERIAL, 0, 0);
+ it->info.serial = s? xstrdup(s) : NULL;
+
+ s = gpgme_key_get_string_attr (key, GPGME_ATTR_FPR, 0, 0);
+ it->info.fingerprint = make_fingerprint( s );
+
+ s = gpgme_key_get_string_attr (key, GPGME_ATTR_ISSUER, 0, 0);
+ if( s ) {
+ issuer_dn = tmp_dn = parse_dn( s );
+ /*it->info.issuer = xstrdup(s);*/
+ it->info.issuer = reorder_dn( issuer_dn );
+ while( tmp_dn && tmp_dn->key ) {
+ free( tmp_dn->key );
+ free( tmp_dn->value );
+ ++tmp_dn;
+ }
+ free( issuer_dn );
+ issuer_dn = tmp_dn = NULL;
+ } else {
+ it->info.issuer = NULL;
+ }
+ s = gpgme_key_get_string_attr (key, GPGME_ATTR_CHAINID, 0, 0);
+ it->info.chainid = s? xstrdup(s): NULL;
+
+ s = gpgme_key_get_string_attr (key, GPGME_ATTR_KEY_CAPS, 0, 0);
+ it->info.caps = s? xstrdup(s) : NULL;
+
+ u = gpgme_key_get_ulong_attr (key, GPGME_ATTR_CREATED, 0, 0);
+ it->info.created = u;
+
+ u = gpgme_key_get_ulong_attr (key, GPGME_ATTR_EXPIRE, 0, 0);
+ it->info.expire = u;
+
+ u = gpgme_key_get_ulong_attr (key, GPGME_ATTR_IS_SECRET, 0, 0);
+ it->info.secret = u;
+
+ u = gpgme_key_get_ulong_attr (key, GPGME_ATTR_UID_INVALID, 0, 0);
+ it->info.invalid = u;
+
+ u = gpgme_key_get_ulong_attr (key, GPGME_ATTR_KEY_EXPIRED, 0, 0);
+ it->info.expired = u;
+
+ u = gpgme_key_get_ulong_attr (key, GPGME_ATTR_KEY_DISABLED, 0, 0);
+ it->info.disabled = u;
+
+ gpgme_key_release (key);
+ /*return &(it->info);*/
+ *result = &(it->info);
+ } else {
+ *result = NULL;
+ }
+ return retval;
+}
+
+int
+endListCertificates( struct CertIterator* it )
+{
+ char *s = gpgme_get_op_info (it->ctx, 0);
+ int truncated = s && strstr (s, "<truncated/>");
+ fprintf( stderr, "endListCertificates( %p )\n", it );
+ if( s ) free( s );
+ assert(it);
+ freeInfo( &(it->info) );
+ gpgme_op_keylist_end(it->ctx);
+ gpgme_release (it->ctx);
+ free( it );
+ return truncated;
+}
+
+int
+importCertificateWithFPR( const char* fingerprint, char** additional_info )
+{
+ GpgmeError err;
+ GpgmeCtx ctx;
+ GpgmeData keydata;
+ GpgmeRecipients recips;
+ char* buf;
+ const char* tmp1;
+ char* tmp2;
+ int count = 0;
+
+ err = gpgme_new( &ctx );
+ /*fprintf( stderr, "2: gpgme returned %d\n", err );*/
+ if( err != GPGME_No_Error ) {
+ return err;
+ }
+ gpgme_set_protocol( ctx, GPGME_PROTOCOL_CMS );
+ gpgme_set_keylist_mode( ctx, GPGME_KEYLIST_MODE_LOCAL );
+
+ err = gpgme_data_new( &keydata );
+ if( err ) {
+ fprintf( stderr, "gpgme_data_new returned %d\n", err );
+ gpgme_release( ctx );
+ return err;
+ }
+
+ err = gpgme_recipients_new( &recips );
+ if( err ) {
+ fprintf( stderr, "gpgme_recipients_new returned %d\n", err );
+ gpgme_data_release( keydata );
+ gpgme_release( ctx );
+ return err;
+ }
+
+ buf = malloc( sizeof(char)*( strlen( fingerprint ) + 1 ) );
+ if( !buf ) {
+ gpgme_recipients_release( recips );
+ gpgme_data_release( keydata );
+ gpgme_release( ctx );
+ return GPGME_Out_Of_Core;
+ }
+ tmp1 = fingerprint;
+ tmp2 = buf;
+ while( *tmp1 ) {
+ if( *tmp1 != ':' ) *tmp2++ = *tmp1;
+ tmp1++;
+ }
+ *tmp2 = 0;
+ fprintf( stderr, "calling gpgme_recipients_add_name( %s )\n", buf );
+ err = gpgme_recipients_add_name( recips, buf );
+ if( err ) {
+ fprintf( stderr, "gpgme_recipients_add_name returned %d\n", err );
+ free (buf);
+ gpgme_recipients_release( recips );
+ gpgme_data_release( keydata );
+ gpgme_release( ctx );
+ return err;
+ }
+
+ err = gpgme_op_export( ctx, recips, keydata );
+ if( err ) {
+ fprintf( stderr, "gpgme_op_export returned %d\n", err );
+ free (buf);
+ *additional_info = gpgme_get_op_info( ctx, 0 );
+ gpgme_recipients_release( recips );
+ gpgme_data_release( keydata );
+ gpgme_release( ctx );
+ return err;
+ }
+ free (buf);
+ buf = NULL;
+
+ err = gpgme_op_import_ext( ctx, keydata, &count );
+ *additional_info = gpgme_get_op_info( ctx, 0 );
+ if( err ) {
+ fprintf( stderr, "gpgme_op_import_ext returned %d\n", err );
+ gpgme_recipients_release( recips );
+ gpgme_data_release( keydata );
+ gpgme_release( ctx );
+ return err;
+ }
+ if( count < 1 ) {
+ /* we didn't import anything?!? */
+ fprintf( stderr, "gpgme_op_import_ext did not import any certificates\n" );
+ gpgme_recipients_release( recips );
+ gpgme_data_release( keydata );
+ gpgme_release( ctx );
+ return -1; /* FIXME */
+ }
+
+ gpgme_recipients_release( recips );
+ gpgme_data_release( keydata );
+ gpgme_release( ctx );
+ return 0;
+}
+int
+importCertificateFromMem( const char* data, size_t length , char** additional_info )
+{
+ GpgmeError err;
+ GpgmeCtx ctx;
+ GpgmeData keydata;
+ int count = 0;
+
+ err = gpgme_new( &ctx );
+ /*fprintf( stderr, "2: gpgme returned %d\n", err );*/
+ if( err != GPGME_No_Error ) {
+ return err;
+ }
+ gpgme_set_protocol( ctx, GPGME_PROTOCOL_CMS );
+ gpgme_set_keylist_mode( ctx, GPGME_KEYLIST_MODE_LOCAL );
+
+ err = gpgme_data_new_from_mem( &keydata, data, length, 0 );
+ if( err ) {
+ fprintf( stderr, "gpgme_data_new returned %d\n", err );
+ gpgme_release( ctx );
+ return err;
+ }
+
+ err = gpgme_op_import_ext( ctx, keydata, &count );
+ *additional_info = gpgme_get_op_info( ctx, 0 );
+ if( err) {
+ fprintf( stderr, "gpgme_op_import_ext returned %d\n", err );
+ gpgme_data_release( keydata );
+ gpgme_release( ctx );
+ return err;
+ }
+ if( count < 1 ) {
+ /* we didn't import anything?!? */
+ fprintf( stderr, "gpgme_op_import_ext did not import any certificate\n" );
+ gpgme_data_release( keydata );
+ gpgme_release( ctx );
+ return -1; /* FIXME */
+ }
+
+ gpgme_data_release( keydata );
+ gpgme_release( ctx );
+ return 0;
+}
+
+/* == == == == == == == == == == == == == == == == == == == == == == == == ==
+ == ==
+ == Continuation of CryptPlug code ==
+ == ==
+== == == == == == == == == == == == == == == == == == == == == == == == == */
+
+
+/*
+ Find all certificate for a given addressee and return them in a
+ '\1' separated list.
+ NOTE: The certificate parameter must point to a not-yet allocated
+ char*. The function will allocate the memory needed and
+ return the size in newSize.
+ If secretOnly is true, only secret keys are returned.
+*/
+bool findCertificates( const char* addressee,
+ char** certificates,
+ int* newSize,
+ bool secretOnly )
+{
+#define MAXCERTS 1024
+ /* use const char declarations since all of them are needed twice */
+ const char* delimiter = "\1";
+ const char* openBracket = " (";
+ const char* closeBracket = ")";
+
+ GpgmeCtx ctx;
+ GpgmeError err;
+ GpgmeKey rKey;
+ const char *s;
+ const char *s2;
+ char* dn;
+ struct DnPair* a;
+ int nFound = 0;
+ int iFound = 0;
+ int siz = 0;
+ char* DNs[MAXCERTS];
+ char* FPRs[MAXCERTS];
+
+ if( ! certificates ){
+ fprintf( stderr, "gpgme: findCertificates called with invalid *certificates pointer\n" );
+ return false;
+ }
+
+ if( ! newSize ){
+ fprintf( stderr, "gpgme: findCertificates called with invalid newSize pointer\n" );
+ return false;
+ }
+
+ *certificates = 0;
+ *newSize = 0;
+
+ /* calculate length of buffer needed for certs plus fingerprints */
+ gpgme_new (&ctx);
+ gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
+ err = gpgme_op_keylist_start(ctx, addressee, secretOnly ? 1 : 0);
+ while( GPGME_No_Error == err ) {
+ err = gpgme_op_keylist_next(ctx, &rKey);
+ if( GPGME_No_Error == err ) {
+ s = gpgme_key_get_string_attr (rKey, GPGME_ATTR_USERID, NULL, 0);
+ if( s ) {
+ dn = xstrdup( s );
+ s2 = gpgme_key_get_string_attr (rKey, GPGME_ATTR_FPR, NULL, 0);
+ if( s2 ) {
+ if( nFound )
+ siz += strlen( delimiter );
+ a = parse_dn( dn );
+ free( dn );
+ dn = reorder_dn( a );
+ siz += strlen( dn );
+ siz += strlen( openBracket );
+ siz += strlen( s2 );
+ siz += strlen( closeBracket );
+ DNs[ nFound ] = dn;
+ dn = NULL; /* prevent it from being free'ed below. */
+ FPRs[nFound ] = xstrdup( s2 );
+ ++nFound;
+ if( nFound >= MAXCERTS ) {
+ fprintf( stderr,
+ "gpgme: findCertificates found too many certificates (%d)\n",
+ MAXCERTS );
+ break;
+ }
+ }
+ free (dn);
+ }
+ }
+ }
+ gpgme_op_keylist_end( ctx );
+ gpgme_release (ctx);
+
+
+ if( 0 < siz ) {
+ /* add one for trailing ZERO char */
+ ++siz;
+ *newSize = siz;
+ /* allocate the buffer */
+ *certificates = xmalloc( sizeof(char) * siz );
+ memset( *certificates, 0, sizeof(char) * siz );
+ /* fill the buffer */
+ for (iFound=0; iFound < nFound; iFound++) {
+ if( !iFound )
+ strcpy(*certificates, DNs[iFound] );
+ else {
+ strcat(*certificates, delimiter );
+ strcat(*certificates, DNs[iFound] );
+ }
+ strcat( *certificates, openBracket );
+ strcat( *certificates, FPRs[iFound] );
+ strcat( *certificates, closeBracket );
+ free( DNs[ iFound ] );
+ free( FPRs[iFound ] );
+ }
+ }
+
+ return ( 0 < nFound );
+}
+
+
+static const char*
+sig_status_to_string( GpgmeSigStat status )
+{
+ const char *result;
+
+ switch (status) {
+ case GPGME_SIG_STAT_NONE:
+ result = "Oops: Signature not verified";
+ break;
+ case GPGME_SIG_STAT_NOSIG:
+ result = "No signature found";
+ break;
+ case GPGME_SIG_STAT_GOOD:
+ result = "Good signature";
+ break;
+ case GPGME_SIG_STAT_BAD:
+ result = "BAD signature";
+ break;
+ case GPGME_SIG_STAT_NOKEY:
+ result = "No public key to verify the signature";
+ break;
+ case GPGME_SIG_STAT_ERROR:
+ result = "Error verifying the signature";
+ break;
+ case GPGME_SIG_STAT_DIFF:
+ result = "Different results for signatures";
+ break;
+ default:
+ result = "Error: Unknown status";
+ break;
+ }
+
+ return result;
+}
+
+
+void obtain_signature_information( GpgmeCtx * ctx,
+ GpgmeSigStat status,
+ struct SignatureMetaData* sigmeta )
+{
+ GpgmeError err;
+ GpgmeKey key;
+ const char* statusStr;
+ const char* fpr;
+ unsigned long sumGPGME;
+ SigStatusFlags sumPlug;
+ time_t created;
+ struct DnPair* a;
+ int sig_idx=0;
+ int UID_idx=0;
+
+ /* Provide information in the sigmeta struct */
+ /* the status string */
+ statusStr = sig_status_to_string( status );
+ sigmeta->status = malloc( strlen( statusStr ) + 1 );
+ if( sigmeta->status ) {
+ strcpy( sigmeta->status, statusStr );
+ sigmeta->status[strlen( statusStr )] = '\0';
+ } else
+ ; /* nothing to do, is already 0 */
+
+ /* Extended information for any number of signatures. */
+ fpr = gpgme_get_sig_status( *ctx, sig_idx, &status, &created );
+ sigmeta->extended_info = 0;
+ while( fpr != NULL ) {
+ struct tm* ctime_val;
+ const char* sig_status;
+
+ void* alloc_return = realloc( sigmeta->extended_info,
+ sizeof( struct SignatureMetaDataExtendedInfo )
+ * ( sig_idx + 1 ) );
+ if( alloc_return ) {
+ sigmeta->extended_info = alloc_return;
+
+ /* clear the data area */
+ memset( &sigmeta->extended_info[sig_idx],
+ 0,
+ sizeof (struct SignatureMetaDataExtendedInfo) );
+
+ /* the creation time */
+ sigmeta->extended_info[sig_idx].creation_time = malloc( sizeof( struct tm ) );
+ if( sigmeta->extended_info[sig_idx].creation_time ) {
+ ctime_val = localtime( &created );
+ memcpy( sigmeta->extended_info[sig_idx].creation_time,
+ ctime_val, sizeof( struct tm ) );
+ }
+
+ /* the extended signature verification status */
+ sumGPGME = gpgme_get_sig_ulong_attr( *ctx,
+ sig_idx,
+ GPGME_ATTR_SIG_SUMMARY,
+ 0 );
+ fprintf( stderr, "gpgmeplug checkMessageSignature status flags: %lX\n", sumGPGME );
+ /* translate GPGME status flags to common CryptPlug status flags */
+ sumPlug = 0;
+ if( sumGPGME & GPGME_SIGSUM_VALID ) sumPlug |= SigStat_VALID ;
+ if( sumGPGME & GPGME_SIGSUM_GREEN ) sumPlug |= SigStat_GREEN ;
+ if( sumGPGME & GPGME_SIGSUM_RED ) sumPlug |= SigStat_RED ;
+ if( sumGPGME & GPGME_SIGSUM_KEY_REVOKED ) sumPlug |= SigStat_KEY_REVOKED;
+ if( sumGPGME & GPGME_SIGSUM_KEY_EXPIRED ) sumPlug |= SigStat_KEY_EXPIRED;
+ if( sumGPGME & GPGME_SIGSUM_SIG_EXPIRED ) sumPlug |= SigStat_SIG_EXPIRED;
+ if( sumGPGME & GPGME_SIGSUM_KEY_MISSING ) sumPlug |= SigStat_KEY_MISSING;
+ if( sumGPGME & GPGME_SIGSUM_CRL_MISSING ) sumPlug |= SigStat_CRL_MISSING;
+ if( sumGPGME & GPGME_SIGSUM_CRL_TOO_OLD ) sumPlug |= SigStat_CRL_TOO_OLD;
+ if( sumGPGME & GPGME_SIGSUM_BAD_POLICY ) sumPlug |= SigStat_BAD_POLICY ;
+ if( sumGPGME & GPGME_SIGSUM_SYS_ERROR ) sumPlug |= SigStat_SYS_ERROR ;
+ if( !sumPlug )
+ sumPlug = SigStat_NUMERICAL_CODE | sumGPGME;
+ sigmeta->extended_info[sig_idx].sigStatusFlags = sumPlug;
+
+ sigmeta->extended_info[sig_idx].validity = GPGME_VALIDITY_UNKNOWN;
+
+ err = gpgme_get_sig_key (*ctx, sig_idx, &key);
+
+ if ( err == GPGME_No_Error) {
+ const char* attr_string;
+ unsigned long attr_ulong;
+
+ /* extract key identidy */
+ attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_KEYID, 0, 0);
+ if (attr_string != 0)
+ storeNewCharPtr( &sigmeta->extended_info[sig_idx].keyid, attr_string );
+
+ /* extract finger print */
+ attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_FPR, 0, 0);
+ if (attr_string != 0)
+ storeNewCharPtr( &sigmeta->extended_info[sig_idx].fingerprint,
+ attr_string );
+
+ /* algorithms useable with this key */
+ attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_ALGO, 0, 0);
+ if (attr_string != 0)
+ storeNewCharPtr( &sigmeta->extended_info[sig_idx].algo,
+ attr_string );
+ attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_ALGO, 0, 0);
+ sigmeta->extended_info[sig_idx].algo_num = attr_ulong;
+
+ /* extract key validity */
+ attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_VALIDITY, 0, 0);
+ sigmeta->extended_info[sig_idx].validity = attr_ulong;
+
+ /* extract user id, according to the documentation it's representable
+ * as a number, but it seems that it also has a string representation
+ */
+ attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_USERID, 0, 0);
+ if (attr_string != 0) {
+ a = parse_dn( attr_string );
+ sigmeta->extended_info[sig_idx].userid = reorder_dn( a );
+ }
+
+ attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_USERID, 0, 0);
+ sigmeta->extended_info[sig_idx].userid_num = attr_ulong;
+
+ /* extract the length */
+ sigmeta->extended_info[sig_idx].keylen = attr_ulong;
+
+ /* extract the creation time of the key */
+ attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_CREATED, 0, 0);
+ sigmeta->extended_info[sig_idx].key_created = attr_ulong;
+
+ /* extract the expiration time of the key */
+ attr_ulong = gpgme_key_get_ulong_attr(key, GPGME_ATTR_EXPIRE, 0, 0);
+ sigmeta->extended_info[sig_idx].key_expires = attr_ulong;
+
+ /* extract user name */
+ attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_NAME, 0, 0);
+ if (attr_string != 0) {
+ a = parse_dn( attr_string );
+ sigmeta->extended_info[sig_idx].name = reorder_dn( a );
+ }
+
+ /* extract email(s) */
+ sigmeta->extended_info[sig_idx].emailCount = 0;
+ sigmeta->extended_info[sig_idx].emailList = 0;
+ for( UID_idx=0;
+ (attr_string = gpgme_key_get_string_attr(key,
+ GPGME_ATTR_EMAIL, 0, UID_idx));
+ ++UID_idx ){
+ if (*attr_string) {
+ fprintf( stderr, "gpgmeplug checkMessageSignature found email: %s\n", attr_string );
+ if( !sigmeta->extended_info[sig_idx].emailCount )
+ alloc_return =
+ malloc( sizeof( char*) );
+ else
+ alloc_return =
+ realloc( sigmeta->extended_info[sig_idx].emailList,
+ sizeof( char*)
+ * (sigmeta->extended_info[sig_idx].emailCount + 1) );
+ if( alloc_return ) {
+ sigmeta->extended_info[sig_idx].emailList = alloc_return;
+ storeNewCharPtr(
+ &( sigmeta->extended_info[sig_idx].emailList[
+ sigmeta->extended_info[sig_idx].emailCount ] ),
+ attr_string );
+ ++sigmeta->extended_info[sig_idx].emailCount;
+ }
+ }
+ }
+ if( !sigmeta->extended_info[sig_idx].emailCount )
+ fprintf( stderr, "gpgmeplug checkMessageSignature found NO EMAIL\n" );
+
+ /* extract the comment */
+ attr_string = gpgme_key_get_string_attr(key, GPGME_ATTR_COMMENT, 0, 0);
+ if (attr_string != 0)
+ storeNewCharPtr( &sigmeta->extended_info[sig_idx].comment,
+ attr_string );
+ }
+ else
+ storeNewCharPtr( &sigmeta->extended_info[sig_idx].fingerprint, fpr );
+
+ sig_status = sig_status_to_string( status );
+ storeNewCharPtr( &sigmeta->extended_info[sig_idx].status_text,
+ sig_status );
+
+ } else
+ break; /* if allocation fails once, it isn't likely to
+ succeed the next time either */
+
+ fpr = gpgme_get_sig_status (*ctx, ++sig_idx, &status, &created);
+ }
+ sigmeta->extended_info_count = sig_idx;
+ sigmeta->nota_xml = gpgme_get_notation( *ctx );
+ sigmeta->status_code = status;
+}
+
+
+bool checkMessageSignature( char** cleartext,
+ const char* signaturetext,
+ bool signatureIsBinary,
+ int signatureLen,
+ struct SignatureMetaData* sigmeta )
+{
+ GpgmeCtx ctx;
+ GpgmeSigStat status;
+ GpgmeData datapart, sigpart;
+ char* rClear = 0;
+ size_t clearLen;
+ bool isOpaqueSigned;
+
+ if( !cleartext ) {
+ if( sigmeta )
+ storeNewCharPtr( &sigmeta->status,
+ __GPGMEPLUG_ERROR_CLEARTEXT_IS_ZERO );
+
+ return false;
+ }
+
+ isOpaqueSigned = !*cleartext;
+
+ gpgme_new( &ctx );
+ gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
+ gpgme_set_armor (ctx, signatureIsBinary ? 0 : 1);
+ /* gpgme_set_textmode (ctx, signatureIsBinary ? 0 : 1); */
+
+ if( isOpaqueSigned )
+ gpgme_data_new( &datapart );
+ else
+ gpgme_data_new_from_mem( &datapart, *cleartext,
+ strlen( *cleartext ), 1 );
+
+ gpgme_data_new_from_mem( &sigpart,
+ signaturetext,
+ signatureIsBinary
+ ? signatureLen
+ : strlen( signaturetext ),
+ 1 );
+
+ gpgme_op_verify( ctx, sigpart, datapart, &status );
+
+ if( isOpaqueSigned ) {
+ rClear = gpgme_data_release_and_get_mem( datapart, &clearLen );
+ *cleartext = malloc( clearLen + 1 );
+ if( *cleartext ) {
+ if( clearLen )
+ strncpy(*cleartext, rClear, clearLen );
+ (*cleartext)[clearLen] = '\0';
+ }
+ free( rClear );
+ }
+ else
+ gpgme_data_release( datapart );
+
+ gpgme_data_release( sigpart );
+
+ obtain_signature_information( &ctx, status, sigmeta );
+
+ gpgme_release( ctx );
+ return ( status == GPGME_SIG_STAT_GOOD );
+}
+
+
+bool decryptAndCheckMessage( const char* ciphertext,
+ bool cipherIsBinary,
+ int cipherLen,
+ const char** cleartext,
+ const char* certificate,
+ bool* signatureFound,
+ struct SignatureMetaData* sigmeta,
+ int* errId,
+ char** errTxt )
+{
+ GpgmeCtx ctx;
+ GpgmeError err;
+ GpgmeSigStat sigstatus;
+ GpgmeData gCiphertext, gPlaintext;
+ size_t rCLen = 0;
+ char* rCiph = 0;
+ bool bOk = false;
+
+ if( !ciphertext )
+ return false;
+
+ err = gpgme_new (&ctx);
+ gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL);
+
+ gpgme_set_armor (ctx, cipherIsBinary ? 0 : 1);
+ /* gpgme_set_textmode (ctx, cipherIsBinary ? 0 : 1); */
+
+ /*
+ gpgme_data_new_from_mem( &gCiphertext, ciphertext,
+ 1+strlen( ciphertext ), 1 ); */
+ gpgme_data_new_from_mem( &gCiphertext,
+ ciphertext,
+ cipherIsBinary
+ ? cipherLen
+ : strlen( ciphertext ),
+ 1 );
+
+ gpgme_data_new( &gPlaintext );
+
+ err = gpgme_op_decrypt_verify( ctx, gCiphertext, gPlaintext, &sigstatus );
+ gpgme_data_release( gCiphertext );
+ if( err ) {
+ fprintf( stderr, "\ngpgme_op_decrypt_verify() returned this error code: %i\n\n", err );
+ if( errId )
+ *errId = err;
+ if( errTxt ) {
+ const char* _errTxt = gpgme_strerror( err );
+ *errTxt = malloc( strlen( _errTxt ) + 1 );
+ if( *errTxt )
+ strcpy(*errTxt, _errTxt );
+ }
+ gpgme_data_release( gPlaintext );
+ gpgme_release( ctx );
+ return bOk;
+ }
+
+ rCiph = gpgme_data_release_and_get_mem( gPlaintext, &rCLen );
+
+ *cleartext = malloc( rCLen + 1 );
+ if( *cleartext ) {
+ if( rCLen ) {
+ bOk = true;
+ strncpy((char*)*cleartext, rCiph, rCLen );
+ }
+ ((char*)(*cleartext))[rCLen] = 0;
+ }
+ free( rCiph );
+
+ if( signatureFound )
+ *signatureFound = sigstatus != GPGME_SIG_STAT_NONE;
+ if( sigmeta && sigstatus != GPGME_SIG_STAT_NONE )
+ obtain_signature_information( &ctx, sigstatus, sigmeta );
+
+ gpgme_release( ctx );
+ return bOk;
+}
diff --git a/branches/gpgme-0-3-branch/gpgmeplug/gpgmeplug.dox b/branches/gpgme-0-3-branch/gpgmeplug/gpgmeplug.dox
new file mode 100644
index 00000000..3dd9d54e
--- /dev/null
+++ b/branches/gpgme-0-3-branch/gpgmeplug/gpgmeplug.dox
@@ -0,0 +1,121 @@
+# Doxygen configuration generated by Doxywizard version 0.1
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = GPGMEPLUG
+PROJECT_NUMBER = 0
+OUTPUT_DIRECTORY = doc/
+OUTPUT_LANGUAGE = English
+QUIET = NO
+WARNINGS = YES
+DISABLE_INDEX = NO
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = NO
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ALWAYS_DETAILED_SEC = NO
+FULL_PATH_NAMES = NO
+STRIP_FROM_PATH =
+INTERNAL_DOCS = NO
+CLASS_DIAGRAMS = YES
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+CASE_SENSE_NAMES = NO
+VERBATIM_HEADERS = YES
+SHOW_INCLUDE_FILES = YES
+JAVADOC_AUTOBRIEF = YES
+INHERIT_DOCS = YES
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+TAB_SIZE = 8
+ENABLED_SECTIONS =
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = .
+FILE_PATTERNS = *.h \
+ *.c
+RECURSIVE = YES
+EXCLUDE =
+EXCLUDE_PATTERNS = moc_*
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS =
+IMAGE_PATH =
+INPUT_FILTER =
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = NO
+COLS_IN_ALPHA_INDEX = 5
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = YES
+LATEX_OUTPUT = latex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4wide
+EXTRA_PACKAGES =
+LATEX_HEADER =
+PDF_HYPERLINKS = NO
+LATEX_BATCHMODE = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = YES
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = NO
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+PREDEFINED =
+EXPAND_ONLY_PREDEF = NO
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references
+#---------------------------------------------------------------------------
+TAGFILES =
+GENERATE_TAGFILE =
+ALLEXTERNALS = NO
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+HAVE_DOT = NO
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+INCLUDE_GRAPH = YES
+GRAPHICAL_HIERARCHY = YES
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
+CGI_NAME = search.cgi
+CGI_URL =
+DOC_URL =
+DOC_ABSPATH =
+BIN_ABSPATH = /usr/local/bin/
+EXT_DOC_PATHS =