diff options
-rw-r--r-- | camel/ChangeLog | 11 | ||||
-rw-r--r-- | camel/Makefile.am | 2 | ||||
-rw-r--r-- | camel/camel-cipher-context.c | 438 | ||||
-rw-r--r-- | camel/camel-cipher-context.h | 122 | ||||
-rw-r--r-- | camel/camel-pgp-context.c | 324 | ||||
-rw-r--r-- | camel/camel-pgp-context.h | 56 | ||||
-rw-r--r-- | camel/camel-pgp-mime.c | 14 | ||||
-rw-r--r-- | camel/camel-pgp-mime.h | 8 |
8 files changed, 662 insertions, 313 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index ea82773fd8..af52d3f97a 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,14 @@ +2001-04-12 Jeffrey Stedfast <fejj@ximian.com> + + * camel-pgp-mime.c: Updated to reflect the few changes made to the + CamelPgpContext class. + + * camel-pgp-context.c: Updated to subclass of CamelCipherContext. + + * camel-cipher-context.[c,h]: New base class for + CamelPgpContext. Also contains the replacement for + CamelPgpValidity, CamelCipherValidity. + 2001-04-12 Dan Winship <danw@ximian.com> * camel-mime-filter-crlf.c (filter): Fix a pair of array bounds diff --git a/camel/Makefile.am b/camel/Makefile.am index eb29f5f626..0a42ed8368 100644 --- a/camel/Makefile.am +++ b/camel/Makefile.am @@ -24,6 +24,7 @@ INCLUDES = -I.. -I$(srcdir)/.. \ libcamel_la_SOURCES = \ broken-date-parser.c \ camel-address.c \ + camel-cipher-context.c \ camel-data-wrapper.c \ camel-exception.c \ camel-filter-driver.c \ @@ -97,6 +98,7 @@ libcamelinclude_HEADERS = \ broken-date-parser.h \ camel-address.h \ camel-charset-map.h \ + camel-cipher-context.h \ camel-data-wrapper.h \ camel-exception-list.def \ camel-exception.h \ diff --git a/camel/camel-cipher-context.c b/camel/camel-cipher-context.c new file mode 100644 index 0000000000..07fda80fd2 --- /dev/null +++ b/camel/camel-cipher-context.c @@ -0,0 +1,438 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2001 Ximian, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 Street #330, Boston, MA 02111-1307, USA. + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "camel-cipher-context.h" + +#include <glib.h> + +#include <iconv.h> + +#ifdef ENABLE_THREADS +#include <pthread.h> +#define CIPHER_LOCK(ctx) g_mutex_lock (((CamelCipherContext *) ctx)->priv->lock) +#define CIPHER_UNLOCK(ctx) g_mutex_unlock (((CamelCipherContext *) ctx)->priv->lock); +#else +#define CIPHER_LOCK(ctx) +#define CIPHER_UNLOCK(ctx) +#endif + +#define d(x) + +#define CCCC(k) CAMEL_CIPHER_CONTEXT_CLASS (k) + +struct _CamelCipherContextPrivate { +#ifdef ENABLE_THREADS + GMutex *lock; +#endif +}; + +static int cipher_sign (CamelCipherContext *ctx, const char *userid, CamelCipherHash hash, + CamelStream *istream, CamelStream *ostream, CamelException *ex); +static int cipher_clearsign (CamelCipherContext *context, const char *userid, CamelCipherHash hash, + CamelStream *istream, CamelStream *ostream, CamelException *ex); +static CamelCipherValidity *cipher_verify (CamelCipherContext *context, CamelStream *istream, + CamelStream *sigstream, CamelException *ex); +static int cipher_encrypt (CamelCipherContext *context, gboolean sign, const char *userid, + GPtrArray *recipients, CamelStream *istream, CamelStream *ostream, + CamelException *ex); +static int cipher_decrypt (CamelCipherContext *context, CamelStream *istream, CamelStream *ostream, + CamelException *ex); + +static CamelObjectClass *parent_class; + +static void +camel_cipher_context_init (CamelCipherContext *context) +{ + context->priv = g_new0 (struct _CamelCipherContextPrivate, 1); +#ifdef ENABLE_THREADS + context->priv->lock = g_mutex_new (); +#endif +} + +static void +camel_cipher_context_finalise (CamelObject *o) +{ + CamelCipherContext *context = (CamelCipherContext *)o; + + camel_object_unref (CAMEL_OBJECT (context->session)); + +#ifdef ENABLE_THREADS + g_mutex_free (context->priv->lock); +#endif + + g_free (context->priv); +} + +static void +camel_cipher_context_class_init (CamelCipherContextClass *camel_cipher_context_class) +{ + parent_class = camel_type_get_global_classfuncs (camel_object_get_type ()); + + camel_cipher_context_class->sign = cipher_sign; + camel_cipher_context_class->clearsign = cipher_clearsign; + camel_cipher_context_class->verify = cipher_verify; + camel_cipher_context_class->encrypt = cipher_encrypt; + camel_cipher_context_class->decrypt = cipher_decrypt; +} + +CamelType +camel_cipher_context_get_type (void) +{ + static CamelType type = CAMEL_INVALID_TYPE; + + if (type == CAMEL_INVALID_TYPE) { + type = camel_type_register (camel_object_get_type (), + "CamelCipherContext", + sizeof (CamelCipherContext), + sizeof (CamelCipherContextClass), + (CamelObjectClassInitFunc) camel_cipher_context_class_init, + NULL, + (CamelObjectInitFunc) camel_cipher_context_init, + (CamelObjectFinalizeFunc) camel_cipher_context_finalise); + } + + return type; +} + + +/** + * camel_cipher_context_new: + * @session: CamelSession + * + * This creates a new CamelCipherContext object which is used to sign, + * verify, encrypt and decrypt streams. + * + * Return value: the new CamelCipherContext + **/ +CamelCipherContext * +camel_cipher_context_new (CamelSession *session) +{ + CamelCipherContext *context; + + g_return_val_if_fail (session != NULL, NULL); + + context = CAMEL_CIPHER_CONTEXT (camel_object_new (CAMEL_CIPHER_CONTEXT_TYPE)); + + camel_object_ref (CAMEL_OBJECT (session)); + context->session = session; + + return context; +} + + +/** + * camel_cipher_context_construct: + * @context: CamelCipherContext + * @session: CamelSession + * + * Constucts the CamelCipherContext + **/ +void +camel_cipher_context_construct (CamelCipherContext *context, CamelSession *session) +{ + g_return_if_fail (CAMEL_IS_CIPHER_CONTEXT (context)); + g_return_if_fail (CAMEL_IS_SESSION (session)); + + camel_object_ref (CAMEL_OBJECT (session)); + context->session = session; +} + + +static int +cipher_sign (CamelCipherContext *ctx, const char *userid, CamelCipherHash hash, + CamelStream *istream, CamelStream *ostream, CamelException *ex) +{ + camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, + _("Signing is not supported by this cipher")); + return -1; +} + +/** + * camel_cipher_sign: + * @context: Cipher Context + * @userid: private key to use to sign the stream + * @hash: preferred Message-Integrity-Check hash algorithm + * @istream: input stream + * @ostream: output stream + * @ex: exception + * + * Signs the input stream and writes the resulting signature to the output stream. + * + * Return value: 0 for success or -1 for failure. + **/ +int +camel_cipher_sign (CamelCipherContext *context, const char *userid, CamelCipherHash hash, + CamelStream *istream, CamelStream *ostream, CamelException *ex) +{ + int retval; + + CIPHER_LOCK(context); + + retval = CCCC (context)->sign (context, userid, hash, istream, ostream, ex); + + CIPHER_UNLOCK(context); + + return retval; +} + + +static int +cipher_clearsign (CamelCipherContext *context, const char *userid, CamelCipherHash hash, + CamelStream *istream, CamelStream *ostream, CamelException *ex) +{ + camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, + _("Clearsigning is not supported by this cipher")); + return -1; +} + +/** + * camel_cipher_clearsign: + * @context: Cipher Context + * @userid: key id or email address of the private key to sign with + * @hash: preferred Message-Integrity-Check hash algorithm + * @istream: input stream + * @ostream: output stream + * @ex: exception + * + * Clearsigns the input stream and writes the resulting clearsign to the output stream. + * + * Return value: 0 for success or -1 for failure. + **/ +int +camel_cipher_clearsign (CamelCipherContext *context, const char *userid, CamelCipherHash hash, + CamelStream *istream, CamelStream *ostream, CamelException *ex) +{ + int retval; + + CIPHER_LOCK(context); + + retval = CCCC (context)->clearsign (context, userid, hash, istream, ostream, ex); + + CIPHER_UNLOCK(context); + + return retval; +} + + +static CamelCipherValidity * +cipher_verify (CamelCipherContext *context, CamelStream *istream, + CamelStream *sigstream, CamelException *ex) +{ + camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, + _("Verifying is not supported by this cipher")); + return NULL; +} + +/** + * camel_cipher_verify: + * @context: Cipher Context + * @istream: input stream + * @sigstream: optional detached-signature stream + * @ex: exception + * + * Verifies the signature. If @istream is a clearsigned stream, + * you should pass %NULL as the sigstream parameter. Otherwise + * @sigstream is assumed to be the signature stream and is used to + * verify the integirity of the @istream. + * + * Return value: a CamelCipherValidity structure containing information + * about the integrity of the input stream or %NULL on failure to + * execute at all. + **/ +CamelCipherValidity * +camel_cipher_verify (CamelCipherContext *context, CamelStream *istream, + CamelStream *sigstream, CamelException *ex) +{ + CamelCipherValidity *valid; + + CIPHER_LOCK(context); + + valid = CCCC (context)->verify (context, istream, sigstream, ex); + + CIPHER_UNLOCK(context); + + return valid; +} + + +static int +cipher_encrypt (CamelCipherContext *context, gboolean sign, const char *userid, GPtrArray *recipients, + CamelStream *istream, CamelStream *ostream, CamelException *ex) +{ + camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, + _("Encryption is not supported by this cipher")); + return -1; +} + +/** + * camel_cipher_encrypt: + * @context: Cipher Context + * @sign: sign as well as encrypt + * @userid: key id (or email address) to use when signing (assuming @sign is %TRUE) + * @recipients: an array of recipient key ids and/or email addresses + * @istream: cleartext input stream + * @ostream: ciphertext output stream + * @ex: exception + * + * Encrypts (and optionally signs) the cleartext input stream and + * writes the resulting ciphertext to the output stream. + * + * Return value: 0 for success or -1 for failure. + **/ +int +camel_cipher_encrypt (CamelCipherContext *context, gboolean sign, const char *userid, GPtrArray *recipients, + CamelStream *istream, CamelStream *ostream, CamelException *ex) +{ + int retval; + + CIPHER_LOCK(context); + + retval = CCCC (context)->encrypt (context, sign, userid, recipients, istream, ostream, ex); + + CIPHER_UNLOCK(context); + + return retval; +} + + +static int +cipher_decrypt (CamelCipherContext *context, CamelStream *istream, + CamelStream *ostream, CamelException *ex) +{ + camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, + _("Decryption is not supported by this cipher")); + return -1; +} + +/** + * camel_cipher_decrypt: + * @context: Cipher Context + * @ciphertext: ciphertext stream (ie input stream) + * @cleartext: cleartext stream (ie output stream) + * @ex: exception + * + * Decrypts the ciphertext input stream and writes the resulting + * cleartext to the output stream. + * + * Return value: 0 for success or -1 for failure. + **/ +int +camel_cipher_decrypt (CamelCipherContext *context, CamelStream *istream, + CamelStream *ostream, CamelException *ex) +{ + int retval; + + CIPHER_LOCK(context); + + retval = CCCC (context)->decrypt (context, istream, ostream, ex); + + CIPHER_UNLOCK(context); + + return retval; +} + + +/* Cipher Validity stuff */ +struct _CamelCipherValidity { + gboolean valid; + gchar *description; +}; + +CamelCipherValidity * +camel_cipher_validity_new (void) +{ + CamelCipherValidity *validity; + + validity = g_new (CamelCipherValidity, 1); + validity->valid = FALSE; + validity->description = NULL; + + return validity; +} + +void +camel_cipher_validity_init (CamelCipherValidity *validity) +{ + g_assert (validity != NULL); + + validity->valid = FALSE; + validity->description = NULL; +} + +gboolean +camel_cipher_validity_get_valid (CamelCipherValidity *validity) +{ + if (validity == NULL) + return FALSE; + + return validity->valid; +} + +void +camel_cipher_validity_set_valid (CamelCipherValidity *validity, gboolean valid) +{ + g_assert (validity != NULL); + + validity->valid = valid; +} + +gchar * +camel_cipher_validity_get_description (CamelCipherValidity *validity) +{ + if (validity == NULL) + return NULL; + + return validity->description; +} + +void +camel_cipher_validity_set_description (CamelCipherValidity *validity, const gchar *description) +{ + g_assert (validity != NULL); + + g_free (validity->description); + validity->description = g_strdup (description); +} + +void +camel_cipher_validity_clear (CamelCipherValidity *validity) +{ + g_assert (validity != NULL); + + validity->valid = FALSE; + g_free (validity->description); + validity->description = NULL; +} + +void +camel_cipher_validity_free (CamelCipherValidity *validity) +{ + if (validity == NULL) + return; + + g_free (validity->description); + g_free (validity); +} diff --git a/camel/camel-cipher-context.h b/camel/camel-cipher-context.h new file mode 100644 index 0000000000..a2f0dd885f --- /dev/null +++ b/camel/camel-cipher-context.h @@ -0,0 +1,122 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * + * Copyright 2001 Ximian, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 Street #330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef CAMEL_CIPHER_CONTEXT_H +#define CAMEL_CIPHER_CONTEXT_H + +#include <camel/camel-session.h> +#include <camel/camel-stream.h> +#include <camel/camel-exception.h> + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#define CAMEL_CIPHER_CONTEXT_TYPE (camel_cipher_context_get_type ()) +#define CAMEL_CIPHER_CONTEXT(obj) (CAMEL_CHECK_CAST((obj), CAMEL_CIPHER_CONTEXT_TYPE, CamelCipherContext)) +#define CAMEL_CIPHER_CONTEXT_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_CIPHER_CONTEXT_TYPE, CamelCipherContextClass)) +#define CAMEL_IS_CIPHER_CONTEXT(o) (CAMEL_CHECK_TYPE((o), CAMEL_CIPHER_CONTEXT_TYPE)) + +typedef struct _CamelCipherValidity CamelCipherValidity; + +typedef enum { + CAMEL_CIPHER_HASH_DEFAULT, + CAMEL_CIPHER_HASH_MD5, + CAMEL_CIPHER_HASH_SHA1 +} CamelCipherHash; + +typedef struct _CamelCipherContext { + CamelObject parent_object; + + struct _CamelCipherContextPrivate *priv; + + CamelSession *session; + +} CamelCipherContext; + +typedef struct _CamelCipherContextClass { + CamelObjectClass parent_class; + + int (*sign) (CamelCipherContext *ctx, const char *userid, CamelCipherHash hash, + CamelStream *istream, CamelStream *ostream, CamelException *ex); + + int (*clearsign) (CamelCipherContext *context, const char *userid, CamelCipherHash hash, + CamelStream *istream, CamelStream *ostream, CamelException *ex); + + CamelCipherValidity * (*verify) (CamelCipherContext *context, CamelStream *istream, + CamelStream *sigstream, CamelException *ex); + + int (*encrypt) (CamelCipherContext *context, gboolean sign, const char *userid, + GPtrArray *recipients, CamelStream *istream, CamelStream *ostream, + CamelException *ex); + + int (*decrypt) (CamelCipherContext *context, CamelStream *istream, CamelStream *ostream, + CamelException *ex); + +} CamelCipherContextClass; + +CamelType camel_cipher_context_get_type (void); + +CamelCipherContext *camel_cipher_context_new (CamelSession *session); + +void camel_cipher_context_construct (CamelCipherContext *context, CamelSession *session); + +/* cipher routines */ +int camel_cipher_sign (CamelCipherContext *context, const char *userid, CamelCipherHash hash, + CamelStream *istream, CamelStream *ostream, CamelException *ex); + +int camel_cipher_clearsign (CamelCipherContext *context, const char *userid, CamelCipherHash hash, + CamelStream *istream, CamelStream *ostream, CamelException *ex); + +CamelCipherValidity *camel_cipher_verify (CamelCipherContext *context, CamelStream *istream, CamelStream *sigstream, + CamelException *ex); + +int camel_cipher_encrypt (CamelCipherContext *context, gboolean sign, const char *userid, + GPtrArray *recipients, CamelStream *istream, CamelStream *ostream, + CamelException *ex); + +int camel_cipher_decrypt (CamelCipherContext *context, CamelStream *istream, CamelStream *ostream, + CamelException *ex); + +/* CamelCipherValidity utility functions */ +CamelCipherValidity *camel_cipher_validity_new (void); + +void camel_cipher_validity_init (CamelCipherValidity *validity); + +gboolean camel_cipher_validity_get_valid (CamelCipherValidity *validity); + +void camel_cipher_validity_set_valid (CamelCipherValidity *validity, gboolean valid); + +char *camel_cipher_validity_get_description (CamelCipherValidity *validity); + +void camel_cipher_validity_set_description (CamelCipherValidity *validity, const char *description); + +void camel_cipher_validity_clear (CamelCipherValidity *validity); + +void camel_cipher_validity_free (CamelCipherValidity *validity); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CAMEL_CIPHER_CONTEXT_H */ diff --git a/camel/camel-pgp-context.c b/camel/camel-pgp-context.c index 53da66390b..9414ad3ba2 100644 --- a/camel/camel-pgp-context.c +++ b/camel/camel-pgp-context.c @@ -52,36 +52,31 @@ #include <unistd.h> #include <signal.h> -#ifdef ENABLE_THREADS -#include <pthread.h> -#define PGP_LOCK(ctx) g_mutex_lock (((CamelPgpContext *) ctx)->priv->lock) -#define PGP_UNLOCK(ctx) g_mutex_unlock (((CamelPgpContext *) ctx)->priv->lock); -#else -#define PGP_LOCK(ctx) -#define PGP_UNLOCK(ctx) -#endif - #define d(x) struct _CamelPgpContextPrivate { - CamelSession *session; CamelPgpType type; char *path; - -#ifdef ENABLE_THREADS - GMutex *lock; -#endif }; -static CamelObjectClass *parent_class; +static int pgp_sign (CamelCipherContext *ctx, const char *userid, CamelCipherHash hash, + CamelStream *istream, CamelStream *ostream, CamelException *ex); +static int pgp_clearsign (CamelCipherContext *context, const char *userid, CamelCipherHash hash, + CamelStream *istream, CamelStream *ostream, CamelException *ex); +static CamelCipherValidity *pgp_verify (CamelCipherContext *context, CamelStream *istream, + CamelStream *sigstream, CamelException *ex); +static int pgp_encrypt (CamelCipherContext *context, gboolean sign, const char *userid, + GPtrArray *recipients, CamelStream *istream, CamelStream *ostream, + CamelException *ex); +static int pgp_decrypt (CamelCipherContext *context, CamelStream *istream, CamelStream *ostream, + CamelException *ex); + +static CamelCipherContextClass *parent_class; static void camel_pgp_context_init (CamelPgpContext *context) { context->priv = g_new0 (struct _CamelPgpContextPrivate, 1); -#ifdef ENABLE_THREADS - context->priv->lock = g_mutex_new (); -#endif } static void @@ -89,21 +84,24 @@ camel_pgp_context_finalise (CamelObject *o) { CamelPgpContext *context = (CamelPgpContext *)o; - camel_object_unref (CAMEL_OBJECT (context->priv->session)); - g_free (context->priv->path); -#ifdef ENABLE_THREADS - g_mutex_free (context->priv->lock); -#endif - g_free (context->priv); } static void camel_pgp_context_class_init (CamelPgpContextClass *camel_pgp_context_class) { - parent_class = camel_type_get_global_classfuncs (camel_object_get_type ()); + CamelCipherContextClass *camel_cipher_context_class = + CAMEL_CIPHER_CONTEXT_CLASS (camel_pgp_context_class); + + parent_class = CAMEL_CIPHER_CONTEXT_CLASS (camel_type_get_global_classfuncs (camel_cipher_context_get_type ())); + + camel_cipher_context_class->sign = pgp_sign; + camel_cipher_context_class->clearsign = pgp_clearsign; + camel_cipher_context_class->verify = pgp_verify; + camel_cipher_context_class->encrypt = pgp_encrypt; + camel_cipher_context_class->decrypt = pgp_decrypt; } CamelType @@ -112,7 +110,7 @@ camel_pgp_context_get_type (void) static CamelType type = CAMEL_INVALID_TYPE; if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_object_get_type (), + type = camel_type_register (camel_pgp_context_get_type (), "CamelPgpContext", sizeof (CamelPgpContext), sizeof (CamelPgpContextClass), @@ -121,7 +119,7 @@ camel_pgp_context_get_type (void) (CamelObjectInitFunc) camel_pgp_context_init, (CamelObjectFinalizeFunc) camel_pgp_context_finalise); } - + return type; } @@ -148,8 +146,7 @@ camel_pgp_context_new (CamelSession *session, CamelPgpType type, const char *pat context = CAMEL_PGP_CONTEXT (camel_object_new (CAMEL_PGP_CONTEXT_TYPE)); - camel_object_ref (CAMEL_OBJECT (session)); - context->priv->session = session; + camel_cipher_context_construct (CAMEL_CIPHER_CONTEXT (context), session); context->priv->type = type; context->priv->path = g_strdup (path); @@ -484,23 +481,11 @@ crypto_exec_with_passwd (const char *path, char *argv[], const char *input, int * Public crypto functions *----------------------------------------------------------------------*/ -/** - * camel_pgp_sign: - * @context: PGP Context - * @userid: private key to use to sign the stream - * @hash: preferred Message-Integrity-Check hash algorithm - * @istream: input stream - * @ostream: output stream - * @ex: exception - * - * PGP signs the input stream and writes the resulting signature to the output stream. - * - * Return value: 0 for success or -1 for failure. - **/ -int -camel_pgp_sign (CamelPgpContext *context, const char *userid, CamelPgpHashType hash, - CamelStream *istream, CamelStream *ostream, CamelException *ex) +static int +pgp_sign (CamelCipherContext *ctx, const char *userid, CamelCipherHash hash, + CamelStream *istream, CamelStream *ostream, CamelException *ex) { + CamelPgpContext *context = CAMEL_PGP_CONTEXT (ctx); GByteArray *plaintext; CamelStream *stream; char *argv[20]; @@ -512,8 +497,6 @@ camel_pgp_sign (CamelPgpContext *context, const char *userid, CamelPgpHashType h char passwd_fd[32]; int retval, i; - PGP_LOCK(context); - /* get the plaintext in a form we can use */ plaintext = g_byte_array_new (); stream = camel_stream_mem_new (); @@ -527,7 +510,7 @@ camel_pgp_sign (CamelPgpContext *context, const char *userid, CamelPgpHashType h goto exception; } - passphrase = pgp_get_passphrase (context->priv->session, context->priv->type, (char *) userid); + passphrase = pgp_get_passphrase (ctx->session, context->priv->type, (char *) userid); if (!passphrase) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("No password provided.")); @@ -542,13 +525,13 @@ camel_pgp_sign (CamelPgpContext *context, const char *userid, CamelPgpHashType h } switch (hash) { - case CAMEL_PGP_HASH_TYPE_DEFAULT: + case CAMEL_CIPHER_HASH_DEFAULT: hash_str = NULL; break; - case CAMEL_PGP_HASH_TYPE_MD5: + case CAMEL_CIPHER_HASH_MD5: hash_str = "MD5"; break; - case CAMEL_PGP_HASH_TYPE_SHA1: + case CAMEL_CIPHER_HASH_SHA1: hash_str = "SHA1"; break; default: @@ -645,9 +628,7 @@ camel_pgp_sign (CamelPgpContext *context, const char *userid, CamelPgpHashType h "%s", diagnostics); g_free (diagnostics); g_free (ciphertext); - pgp_forget_passphrase (context->priv->session, context->priv->type, (char *) userid); - - PGP_UNLOCK(context); + pgp_forget_passphrase (ctx->session, context->priv->type, (char *) userid); return -1; } @@ -657,8 +638,6 @@ camel_pgp_sign (CamelPgpContext *context, const char *userid, CamelPgpHashType h camel_stream_write (ostream, ciphertext, strlen (ciphertext)); g_free (ciphertext); - PGP_UNLOCK(context); - return 0; exception: @@ -666,33 +645,19 @@ camel_pgp_sign (CamelPgpContext *context, const char *userid, CamelPgpHashType h g_byte_array_free (plaintext, TRUE); if (passphrase) { - pgp_forget_passphrase (context->priv->session, context->priv->type, (char *) userid); + pgp_forget_passphrase (ctx->session, context->priv->type, (char *) userid); g_free (passphrase); } - PGP_UNLOCK(context); - return -1; } -/** - * camel_pgp_clearsign: - * @context: PGP Context - * @userid: key id or email address of the private key to sign with - * @hash: preferred Message-Integrity-Check hash algorithm - * @istream: input stream - * @ostream: output stream - * @ex: exception - * - * PGP clearsigns the input stream and writes the resulting clearsign to the output stream. - * - * Return value: 0 for success or -1 for failure. - **/ -int -camel_pgp_clearsign (CamelPgpContext *context, const char *userid, CamelPgpHashType hash, - CamelStream *istream, CamelStream *ostream, CamelException *ex) +static int +pgp_clearsign (CamelCipherContext *ctx, const char *userid, CamelCipherHash hash, + CamelStream *istream, CamelStream *ostream, CamelException *ex) { + CamelPgpContext *context = CAMEL_PGP_CONTEXT (ctx); GByteArray *plaintext; CamelStream *stream; char *argv[15]; @@ -704,8 +669,6 @@ camel_pgp_clearsign (CamelPgpContext *context, const char *userid, CamelPgpHashT char passwd_fd[32]; int retval, i; - PGP_LOCK(context); - /* get the plaintext in a form we can use */ plaintext = g_byte_array_new (); stream = camel_stream_mem_new (); @@ -719,7 +682,7 @@ camel_pgp_clearsign (CamelPgpContext *context, const char *userid, CamelPgpHashT goto exception; } - passphrase = pgp_get_passphrase (context->priv->session, context->priv->type, (char *) userid); + passphrase = pgp_get_passphrase (ctx->session, context->priv->type, (char *) userid); if (!passphrase) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("No password provided.")); @@ -734,13 +697,13 @@ camel_pgp_clearsign (CamelPgpContext *context, const char *userid, CamelPgpHashT } switch (hash) { - case CAMEL_PGP_HASH_TYPE_DEFAULT: + case CAMEL_CIPHER_HASH_DEFAULT: hash_str = NULL; break; - case CAMEL_PGP_HASH_TYPE_MD5: + case CAMEL_CIPHER_HASH_MD5: hash_str = "MD5"; break; - case CAMEL_PGP_HASH_TYPE_SHA1: + case CAMEL_CIPHER_HASH_SHA1: hash_str = "SHA1"; break; default: @@ -836,7 +799,7 @@ camel_pgp_clearsign (CamelPgpContext *context, const char *userid, CamelPgpHashT "%s", diagnostics); g_free (diagnostics); g_free (ciphertext); - pgp_forget_passphrase (context->priv->session, context->priv->type, (char *) userid); + pgp_forget_passphrase (ctx->session, context->priv->type, (char *) userid); } g_free (diagnostics); @@ -844,8 +807,6 @@ camel_pgp_clearsign (CamelPgpContext *context, const char *userid, CamelPgpHashT camel_stream_write (ostream, ciphertext, strlen (ciphertext)); g_free (ciphertext); - PGP_UNLOCK(context); - return 0; exception: @@ -853,12 +814,10 @@ camel_pgp_clearsign (CamelPgpContext *context, const char *userid, CamelPgpHashT g_byte_array_free (plaintext, TRUE); if (passphrase) { - pgp_forget_passphrase (context->priv->session, context->priv->type, (char *) userid); + pgp_forget_passphrase (ctx->session, context->priv->type, (char *) userid); g_free (passphrase); } - PGP_UNLOCK(context); - return -1; } @@ -885,27 +844,12 @@ swrite (CamelStream *istream) } -/** - * camel_pgp_verify: - * @context: PGP Context - * @istream: input stream - * @sigstream: optional detached-signature stream - * @ex: exception - * - * Verifies the PGP signature. If @istream is a clearsigned stream, - * you should pass %NULL as the sigstream parameter. Otherwise - * @sigstream is assumed to be the signature stream and is used to - * verify the integirity of the @istream. - * - * Return value: a CamelPgpValidity structure containing information - * about the integrity of the input stream or %NULL if PGP failed to - * execute at all. - **/ -CamelPgpValidity * -camel_pgp_verify (CamelPgpContext *context, CamelStream *istream, - CamelStream *sigstream, CamelException *ex) +static CamelCipherValidity * +pgp_verify (CamelCipherContext *ctx, CamelStream *istream, + CamelStream *sigstream, CamelException *ex) { - CamelPgpValidity *valid = NULL; + CamelPgpContext *context = CAMEL_PGP_CONTEXT (ctx); + CamelCipherValidity *valid = NULL; GByteArray *plaintext; CamelStream *stream; char *argv[20]; @@ -915,8 +859,6 @@ camel_pgp_verify (CamelPgpContext *context, CamelStream *istream, char *sigfile = NULL; int retval, i, clearlen; - PGP_LOCK(context); - /* get the plaintext in a form we can use */ plaintext = g_byte_array_new (); stream = camel_stream_mem_new (); @@ -1009,61 +951,43 @@ camel_pgp_verify (CamelPgpContext *context, CamelStream *istream, g_free (sigfile); } - valid = camel_pgp_validity_new (); + valid = camel_cipher_validity_new (); if (retval != 0) { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, "%s", diagnostics); - camel_pgp_validity_set_valid (valid, FALSE); + camel_cipher_validity_set_valid (valid, FALSE); } else { - camel_pgp_validity_set_valid (valid, TRUE); + camel_cipher_validity_set_valid (valid, TRUE); } if (diagnostics) { char *desc; desc = e_utf8_from_locale_string (diagnostics); - camel_pgp_validity_set_description (valid, desc); + camel_cipher_validity_set_description (valid, desc); g_free (desc); } g_free (diagnostics); g_free (cleartext); - PGP_UNLOCK(context); - return valid; exception: g_byte_array_free (plaintext, TRUE); - PGP_UNLOCK(context); - return NULL; } -/** - * camel_pgp_encrypt: - * @context: PGP Context - * @sign: sign as well as encrypt - * @userid: key id (or email address) to use when signing (assuming @sign is %TRUE) - * @recipients: an array of recipient key ids and/or email addresses - * @istream: cleartext input stream - * @ostream: ciphertext output stream - * @ex: exception - * - * PGP encrypts (and optionally signs) the cleartext input stream and - * writes the resulting ciphertext to the output stream. - * - * Return value: 0 for success or -1 for failure. - **/ -int -camel_pgp_encrypt (CamelPgpContext *context, gboolean sign, const char *userid, GPtrArray *recipients, - CamelStream *istream, CamelStream *ostream, CamelException *ex) +static int +pgp_encrypt (CamelCipherContext *ctx, gboolean sign, const char *userid, GPtrArray *recipients, + CamelStream *istream, CamelStream *ostream, CamelException *ex) { + CamelPgpContext *context = CAMEL_PGP_CONTEXT (ctx); GPtrArray *recipient_list = NULL; GByteArray *plaintext; CamelStream *stream; @@ -1075,8 +999,6 @@ camel_pgp_encrypt (CamelPgpContext *context, gboolean sign, const char *userid, char passwd_fd[32]; char *passphrase = NULL; - PGP_LOCK(context); - /* get the plaintext in a form we can use */ plaintext = g_byte_array_new (); stream = camel_stream_mem_new (); @@ -1092,7 +1014,7 @@ camel_pgp_encrypt (CamelPgpContext *context, gboolean sign, const char *userid, if (sign) { /* we only need a passphrase if we intend on signing */ - passphrase = pgp_get_passphrase (context->priv->session, context->priv->type, + passphrase = pgp_get_passphrase (ctx->session, context->priv->type, (char *) userid); if (!passphrase) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, @@ -1249,11 +1171,9 @@ camel_pgp_encrypt (CamelPgpContext *context, gboolean sign, const char *userid, g_free (diagnostics); g_free (ciphertext); if (sign) - pgp_forget_passphrase (context->priv->session, context->priv->type, + pgp_forget_passphrase (ctx->session, context->priv->type, (char *) userid); - PGP_UNLOCK(context); - return -1; } @@ -1262,8 +1182,6 @@ camel_pgp_encrypt (CamelPgpContext *context, gboolean sign, const char *userid, camel_stream_write (ostream, ciphertext, strlen (ciphertext)); g_free (ciphertext); - PGP_UNLOCK(context); - return 0; exception: @@ -1272,31 +1190,18 @@ camel_pgp_encrypt (CamelPgpContext *context, gboolean sign, const char *userid, if (sign) { g_free (passphrase); - pgp_forget_passphrase (context->priv->session, context->priv->type, (char *) userid); + pgp_forget_passphrase (ctx->session, context->priv->type, (char *) userid); } - PGP_UNLOCK(context); - return -1; } -/** - * camel_pgp_encrypt: - * @context: PGP Context - * @ciphertext: ciphertext stream (ie input stream) - * @cleartext: cleartext stream (ie output stream) - * @ex: exception - * - * PGP decrypts the ciphertext input stream and writes the resulting - * cleartext to the output stream. - * - * Return value: 0 for success or -1 for failure. - **/ -int -camel_pgp_decrypt (CamelPgpContext *context, CamelStream *istream, - CamelStream *ostream, CamelException *ex) +static int +pgp_decrypt (CamelCipherContext *ctx, CamelStream *istream, + CamelStream *ostream, CamelException *ex) { + CamelPgpContext *context = CAMEL_PGP_CONTEXT (ctx); GByteArray *ciphertext; CamelStream *stream; char *argv[15]; @@ -1308,7 +1213,7 @@ camel_pgp_decrypt (CamelPgpContext *context, CamelStream *istream, char passwd_fd[32]; int retval, i; - PGP_LOCK(context); + ctx = CAMEL_CIPHER_CONTEXT (context); /* get the ciphertext in a form we can use */ ciphertext = g_byte_array_new (); @@ -1324,7 +1229,7 @@ camel_pgp_decrypt (CamelPgpContext *context, CamelStream *istream, goto exception; } - passphrase = pgp_get_passphrase (context->priv->session, context->priv->type, NULL); + passphrase = pgp_get_passphrase (ctx->session, context->priv->type, NULL); if (!passphrase) { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("No password provided.")); @@ -1395,9 +1300,7 @@ camel_pgp_decrypt (CamelPgpContext *context, CamelStream *istream, g_free (plaintext); g_free (diagnostics); - pgp_forget_passphrase (context->priv->session, context->priv->type, NULL); - - PGP_UNLOCK(context); + pgp_forget_passphrase (ctx->session, context->priv->type, NULL); return -1; } @@ -1407,8 +1310,6 @@ camel_pgp_decrypt (CamelPgpContext *context, CamelStream *istream, camel_stream_write (ostream, plaintext, plainlen); g_free (plaintext); - PGP_UNLOCK(context); - return 0; exception: @@ -1416,94 +1317,9 @@ camel_pgp_decrypt (CamelPgpContext *context, CamelStream *istream, g_byte_array_free (ciphertext, TRUE); if (passphrase) { - pgp_forget_passphrase (context->priv->session, context->priv->type, NULL); + pgp_forget_passphrase (ctx->session, context->priv->type, NULL); g_free (passphrase); } - PGP_UNLOCK(context); - return -1; } - - -/* PGP vailidity stuff */ -struct _CamelPgpValidity { - gboolean valid; - gchar *description; -}; - -CamelPgpValidity * -camel_pgp_validity_new (void) -{ - CamelPgpValidity *validity; - - validity = g_new (CamelPgpValidity, 1); - validity->valid = FALSE; - validity->description = NULL; - - return validity; -} - -void -camel_pgp_validity_init (CamelPgpValidity *validity) -{ - g_assert (validity != NULL); - - validity->valid = FALSE; - validity->description = NULL; -} - -gboolean -camel_pgp_validity_get_valid (CamelPgpValidity *validity) -{ - if (validity == NULL) - return FALSE; - - return validity->valid; -} - -void -camel_pgp_validity_set_valid (CamelPgpValidity *validity, gboolean valid) -{ - g_assert (validity != NULL); - - validity->valid = valid; -} - -gchar * -camel_pgp_validity_get_description (CamelPgpValidity *validity) -{ - if (validity == NULL) - return NULL; - - return validity->description; -} - -void -camel_pgp_validity_set_description (CamelPgpValidity *validity, const gchar *description) -{ - g_assert (validity != NULL); - - g_free (validity->description); - validity->description = g_strdup (description); -} - -void -camel_pgp_validity_clear (CamelPgpValidity *validity) -{ - g_assert (validity != NULL); - - validity->valid = FALSE; - g_free (validity->description); - validity->description = NULL; -} - -void -camel_pgp_validity_free (CamelPgpValidity *validity) -{ - if (validity == NULL) - return; - - g_free (validity->description); - g_free (validity); -} diff --git a/camel/camel-pgp-context.h b/camel/camel-pgp-context.h index 239d15bf3e..0f4f705d64 100644 --- a/camel/camel-pgp-context.h +++ b/camel/camel-pgp-context.h @@ -20,22 +20,13 @@ * */ -/* Once I figure out a nice API for S/MIME, it may be ideal to make a - * new klass `CamelSecurityContext' or somesuch and have - * CamelPgpContext (and the future CamelSMIMEContext) subclass it. - * - * The virtual functions could be sign, (clearsign maybe?,) verify, encrypt, and decrypt - * - * I could also make CamelPgpValidity more generic, maybe call it - * CamelSignatureValidity or somesuch. - */ - #ifndef CAMEL_PGP_CONTEXT_H #define CAMEL_PGP_CONTEXT_H #include <camel/camel-session.h> #include <camel/camel-stream.h> #include <camel/camel-exception.h> +#include <camel/camel-cipher-context.h> #ifdef __cplusplus extern "C" { @@ -55,63 +46,32 @@ typedef enum { CAMEL_PGP_TYPE_GPG } CamelPgpType; -typedef enum { - CAMEL_PGP_HASH_TYPE_DEFAULT, - CAMEL_PGP_HASH_TYPE_MD5, - CAMEL_PGP_HASH_TYPE_SHA1 -} CamelPgpHashType; - typedef struct _CamelPgpContext { - CamelObject parent_object; + CamelCipherContext parent_object; struct _CamelPgpContextPrivate *priv; } CamelPgpContext; typedef struct _CamelPgpContextClass { - CamelObjectClass parent_class; + CamelCipherContextClass parent_class; } CamelPgpContextClass; -typedef struct _CamelPgpValidity CamelPgpValidity; - CamelType camel_pgp_context_get_type (void); CamelPgpContext *camel_pgp_context_new (CamelSession *session, CamelPgpType type, const char *path); /* PGP routines */ -int camel_pgp_sign (CamelPgpContext *context, const char *userid, CamelPgpHashType hash, - CamelStream *istream, CamelStream *ostream, CamelException *ex); - -int camel_pgp_clearsign (CamelPgpContext *context, const char *userid, CamelPgpHashType hash, - CamelStream *istream, CamelStream *ostream, CamelException *ex); - -CamelPgpValidity *camel_pgp_verify (CamelPgpContext *context, CamelStream *istream, CamelStream *sigstream, - CamelException *ex); - -int camel_pgp_encrypt (CamelPgpContext *context, gboolean sign, const char *userid, - GPtrArray *recipients, CamelStream *istream, CamelStream *ostream, - CamelException *ex); - -int camel_pgp_decrypt (CamelPgpContext *context, CamelStream *istream, CamelStream *ostream, - CamelException *ex); - -/* CamelPgpValidity utility functions */ -CamelPgpValidity *camel_pgp_validity_new (void); - -void camel_pgp_validity_init (CamelPgpValidity *validity); - -gboolean camel_pgp_validity_get_valid (CamelPgpValidity *validity); - -void camel_pgp_validity_set_valid (CamelPgpValidity *validity, gboolean valid); +#define camel_pgp_sign(c, u, h, i, o, e) camel_cipher_sign (CAMEL_CIPHER_CONTEXT (c), u, h, i, o, e) -gchar *camel_pgp_validity_get_description (CamelPgpValidity *validity); +#define camel_pgp_clearsign(c, u, h, i, o, e) camel_cipher_clearsign (CAMEL_CIPHER_CONTEXT (c), u, h, i, o, e) -void camel_pgp_validity_set_description (CamelPgpValidity *validity, const gchar *description); +#define camel_pgp_verify(c, i, s, e) camel_cipher_verify (CAMEL_CIPHER_CONTEXT (c), i, s, e) -void camel_pgp_validity_clear (CamelPgpValidity *validity); +#define camel_pgp_encrypt(c, s, u, r, i, o, e) camel_cipher_encrypt (CAMEL_CIPHER_CONTEXT (c), s, u, r, i, o, e) -void camel_pgp_validity_free (CamelPgpValidity *validity); +#define camel_pgp_decrypt(c, i, o, e) camel_cipher_decrypt (CAMEL_CIPHER_CONTEXT (c), i, o, e) #ifdef __cplusplus } diff --git a/camel/camel-pgp-mime.c b/camel/camel-pgp-mime.c index c72fc03f5d..a9eef4e7cc 100644 --- a/camel/camel-pgp-mime.c +++ b/camel/camel-pgp-mime.c @@ -205,7 +205,7 @@ pgp_mime_part_sign_prepare_part (CamelMimePart *mime_part, GSList **encodings) **/ void camel_pgp_mime_part_sign (CamelPgpContext *context, CamelMimePart **mime_part, const char *userid, - CamelPgpHashType hash, CamelException *ex) + CamelCipherHash hash, CamelException *ex) { CamelMimePart *part, *signed_part; CamelMultipart *multipart; @@ -270,15 +270,15 @@ camel_pgp_mime_part_sign (CamelPgpContext *context, CamelMimePart **mime_part, c /* construct the container multipart/signed */ switch (hash) { - case CAMEL_PGP_HASH_TYPE_MD5: + case CAMEL_CIPHER_HASH_MD5: hash_type = "pgp-md5"; break; - case CAMEL_PGP_HASH_TYPE_SHA1: + case CAMEL_CIPHER_HASH_SHA1: hash_type = "pgp-sha1"; break; default: /* set a reasonable default */ - hash = CAMEL_PGP_HASH_TYPE_SHA1; + hash = CAMEL_CIPHER_HASH_SHA1; hash_type = "pgp-sha1"; break; } @@ -313,9 +313,9 @@ camel_pgp_mime_part_sign (CamelPgpContext *context, CamelMimePart **mime_part, c * @mime_part: a multipart/signed MIME Part * @ex: exception * - * Returns a CamelPgpValidity on success or NULL on fail. + * Returns a CamelCipherValidity on success or NULL on fail. **/ -CamelPgpValidity * +CamelCipherValidity * camel_pgp_mime_part_verify (CamelPgpContext *context, CamelMimePart *mime_part, CamelException *ex) { CamelDataWrapper *wrapper; @@ -324,7 +324,7 @@ camel_pgp_mime_part_verify (CamelPgpContext *context, CamelMimePart *mime_part, CamelStreamFilter *filtered_stream; CamelMimeFilter *crlf_filter, *from_filter; CamelStream *stream, *sigstream; - CamelPgpValidity *valid; + CamelCipherValidity *valid; g_return_val_if_fail (mime_part != NULL, NULL); g_return_val_if_fail (CAMEL_IS_MIME_PART (mime_part), NULL); diff --git a/camel/camel-pgp-mime.h b/camel/camel-pgp-mime.h index 026e9a8cac..e9c15e3489 100644 --- a/camel/camel-pgp-mime.h +++ b/camel/camel-pgp-mime.h @@ -41,12 +41,12 @@ gboolean camel_pgp_mime_is_rfc2015_encrypted (CamelMimePart *part); void camel_pgp_mime_part_sign (CamelPgpContext *context, CamelMimePart **mime_part, const char *userid, - CamelPgpHashType hash, + CamelCipherHash hash, CamelException *ex); -CamelPgpValidity *camel_pgp_mime_part_verify (CamelPgpContext *context, - CamelMimePart *mime_part, - CamelException *ex); +CamelCipherValidity *camel_pgp_mime_part_verify (CamelPgpContext *context, + CamelMimePart *mime_part, + CamelException *ex); void camel_pgp_mime_part_encrypt (CamelPgpContext *context, CamelMimePart **mime_part, |