diff options
Diffstat (limited to 'branches/gpgme-0-3-branch/gpgmeplug')
-rw-r--r-- | branches/gpgme-0-3-branch/gpgmeplug/ChangeLog | 189 | ||||
-rw-r--r-- | branches/gpgme-0-3-branch/gpgmeplug/Makefile.am | 39 | ||||
-rw-r--r-- | branches/gpgme-0-3-branch/gpgmeplug/cryptplug.h | 1906 | ||||
-rw-r--r-- | branches/gpgme-0-3-branch/gpgmeplug/gpgme-openpgp.c | 60 | ||||
-rw-r--r-- | branches/gpgme-0-3-branch/gpgmeplug/gpgme-smime.c | 60 | ||||
-rw-r--r-- | branches/gpgme-0-3-branch/gpgmeplug/gpgmeplug.c | 2863 | ||||
-rw-r--r-- | branches/gpgme-0-3-branch/gpgmeplug/gpgmeplug.dox | 121 |
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 = |