diff options
Diffstat (limited to 'camel/camel-cipher-context.c')
-rw-r--r-- | camel/camel-cipher-context.c | 438 |
1 files changed, 438 insertions, 0 deletions
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); +} |