1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Authors: Jeffrey Stedfast <fejj@ximian.com>
5 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of version 2 of the GNU Lesser General Public
9 * License as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
29 #include <glib/gi18n-lib.h>
31 #include "camel-cipher-context.h"
32 #include "camel-debug.h"
33 #include "camel-session.h"
34 #include "camel-stream.h"
35 #include "camel-operation.h"
37 #include "camel-mime-utils.h"
38 #include "camel-medium.h"
39 #include "camel-multipart.h"
40 #include "camel-multipart-encrypted.h"
41 #include "camel-multipart-signed.h"
42 #include "camel-mime-message.h"
43 #include "camel-mime-filter-canon.h"
44 #include "camel-stream-filter.h"
46 #define CAMEL_CIPHER_CONTEXT_GET_PRIVATE(obj) \
47 (G_TYPE_INSTANCE_GET_PRIVATE \
48 ((obj), CAMEL_TYPE_CIPHER_CONTEXT, CamelCipherContextPrivate))
50 #define CIPHER_LOCK(ctx) \
51 g_mutex_lock (&((CamelCipherContext *) ctx)->priv->lock)
52 #define CIPHER_UNLOCK(ctx) \
53 g_mutex_unlock (&((CamelCipherContext *) ctx)->priv->lock);
57 typedef struct _AsyncContext AsyncContext;
59 struct _CamelCipherContextPrivate {
60 CamelSession *session;
64 struct _AsyncContext {
74 CamelCipherValidity *validity;
82 G_DEFINE_TYPE (CamelCipherContext, camel_cipher_context, CAMEL_TYPE_OBJECT)
85 async_context_free (AsyncContext *async_context)
87 if (async_context->ipart != NULL)
88 g_object_unref (async_context->ipart);
90 if (async_context->opart != NULL)
91 g_object_unref (async_context->opart);
93 if (async_context->stream != NULL)
94 g_object_unref (async_context->stream);
96 if (async_context->strings != NULL) {
98 async_context->strings, (GFunc) g_free, NULL);
99 g_ptr_array_free (async_context->strings, TRUE);
102 if (async_context->validity != NULL)
103 camel_cipher_validity_free (async_context->validity);
105 g_free (async_context->userid);
107 g_slice_free (AsyncContext, async_context);
111 cipher_context_set_session (CamelCipherContext *context,
112 CamelSession *session)
114 g_return_if_fail (CAMEL_IS_SESSION (session));
115 g_return_if_fail (context->priv->session == NULL);
117 context->priv->session = g_object_ref (session);
121 cipher_context_set_property (GObject *object,
126 switch (property_id) {
128 cipher_context_set_session (
129 CAMEL_CIPHER_CONTEXT (object),
130 g_value_get_object (value));
134 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
138 cipher_context_get_property (GObject *object,
143 switch (property_id) {
146 value, camel_cipher_context_get_session (
147 CAMEL_CIPHER_CONTEXT (object)));
151 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
155 cipher_context_dispose (GObject *object)
157 CamelCipherContextPrivate *priv;
159 priv = CAMEL_CIPHER_CONTEXT_GET_PRIVATE (object);
161 if (priv->session != NULL) {
162 g_object_unref (priv->session);
163 priv->session = NULL;
166 /* Chain up to parent's dispose () method. */
167 G_OBJECT_CLASS (camel_cipher_context_parent_class)->dispose (object);
171 cipher_context_finalize (GObject *object)
173 CamelCipherContextPrivate *priv;
175 priv = CAMEL_CIPHER_CONTEXT_GET_PRIVATE (object);
177 g_mutex_clear (&priv->lock);
179 /* Chain up to parent's finalize () method. */
180 G_OBJECT_CLASS (camel_cipher_context_parent_class)->finalize (object);
184 cipher_context_hash_to_id (CamelCipherContext *context,
185 CamelCipherHash hash)
190 static CamelCipherHash
191 cipher_context_id_to_hash (CamelCipherContext *context,
194 return CAMEL_CIPHER_HASH_DEFAULT;
198 cipher_context_sign_sync (CamelCipherContext *ctx,
200 CamelCipherHash hash,
201 CamelMimePart *ipart,
202 CamelMimePart *opart,
203 GCancellable *cancellable,
207 error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
208 _("Signing is not supported by this cipher"));
213 static CamelCipherValidity *
214 cipher_context_verify_sync (CamelCipherContext *context,
215 CamelMimePart *sigpart,
216 GCancellable *cancellable,
220 error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
221 _("Verifying is not supported by this cipher"));
227 cipher_context_encrypt_sync (CamelCipherContext *context,
229 GPtrArray *recipients,
230 CamelMimePart *ipart,
231 CamelMimePart *opart,
232 GCancellable *cancellable,
236 error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
237 _("Encryption is not supported by this cipher"));
242 static CamelCipherValidity *
243 cipher_context_decrypt_sync (CamelCipherContext *context,
244 CamelMimePart *ipart,
245 CamelMimePart *opart,
246 GCancellable *cancellable,
250 error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
251 _("Decryption is not supported by this cipher"));
257 cipher_context_import_keys_sync (CamelCipherContext *context,
258 CamelStream *istream,
259 GCancellable *cancellable,
263 error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
264 _("You may not import keys with this cipher"));
270 cipher_context_export_keys_sync (CamelCipherContext *context,
272 CamelStream *ostream,
273 GCancellable *cancellable,
277 error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
278 _("You may not export keys with this cipher"));
284 cipher_context_sign_thread (GSimpleAsyncResult *simple,
286 GCancellable *cancellable)
288 AsyncContext *async_context;
289 GError *error = NULL;
291 async_context = g_simple_async_result_get_op_res_gpointer (simple);
293 camel_cipher_context_sign_sync (
294 CAMEL_CIPHER_CONTEXT (object),
295 async_context->userid, async_context->hash,
296 async_context->ipart, async_context->opart,
297 cancellable, &error);
300 g_simple_async_result_take_error (simple, error);
304 cipher_context_sign (CamelCipherContext *context,
306 CamelCipherHash hash,
307 CamelMimePart *ipart,
308 CamelMimePart *opart,
310 GCancellable *cancellable,
311 GAsyncReadyCallback callback,
314 GSimpleAsyncResult *simple;
315 AsyncContext *async_context;
317 async_context = g_slice_new0 (AsyncContext);
318 async_context->userid = g_strdup (userid);
319 async_context->hash = hash;
320 async_context->ipart = g_object_ref (ipart);
321 async_context->opart = g_object_ref (opart);
323 simple = g_simple_async_result_new (
324 G_OBJECT (context), callback, user_data, cipher_context_sign);
326 g_simple_async_result_set_check_cancellable (simple, cancellable);
328 g_simple_async_result_set_op_res_gpointer (
329 simple, async_context, (GDestroyNotify) async_context_free);
331 g_simple_async_result_run_in_thread (
332 simple, cipher_context_sign_thread, io_priority, cancellable);
334 g_object_unref (simple);
338 cipher_context_sign_finish (CamelCipherContext *context,
339 GAsyncResult *result,
342 GSimpleAsyncResult *simple;
344 g_return_val_if_fail (
345 g_simple_async_result_is_valid (
346 result, G_OBJECT (context), cipher_context_sign), FALSE);
348 simple = G_SIMPLE_ASYNC_RESULT (result);
350 /* Assume success unless a GError is set. */
351 return !g_simple_async_result_propagate_error (simple, error);
355 cipher_context_verify_thread (GSimpleAsyncResult *simple,
357 GCancellable *cancellable)
359 AsyncContext *async_context;
360 GError *error = NULL;
362 async_context = g_simple_async_result_get_op_res_gpointer (simple);
364 async_context->validity = camel_cipher_context_verify_sync (
365 CAMEL_CIPHER_CONTEXT (object), async_context->ipart,
366 cancellable, &error);
369 g_simple_async_result_take_error (simple, error);
373 cipher_context_verify (CamelCipherContext *context,
374 CamelMimePart *ipart,
376 GCancellable *cancellable,
377 GAsyncReadyCallback callback,
380 GSimpleAsyncResult *simple;
381 AsyncContext *async_context;
383 async_context = g_slice_new0 (AsyncContext);
384 async_context->ipart = g_object_ref (ipart);
386 simple = g_simple_async_result_new (
387 G_OBJECT (context), callback,
388 user_data, cipher_context_verify);
390 g_simple_async_result_set_check_cancellable (simple, cancellable);
392 g_simple_async_result_set_op_res_gpointer (
393 simple, async_context, (GDestroyNotify) async_context_free);
395 g_simple_async_result_run_in_thread (
396 simple, cipher_context_verify_thread,
397 io_priority, cancellable);
399 g_object_unref (simple);
402 static CamelCipherValidity *
403 cipher_context_verify_finish (CamelCipherContext *context,
404 GAsyncResult *result,
407 GSimpleAsyncResult *simple;
408 AsyncContext *async_context;
409 CamelCipherValidity *validity;
411 g_return_val_if_fail (
412 g_simple_async_result_is_valid (
413 result, G_OBJECT (context), cipher_context_verify), NULL);
415 simple = G_SIMPLE_ASYNC_RESULT (result);
416 async_context = g_simple_async_result_get_op_res_gpointer (simple);
418 if (g_simple_async_result_propagate_error (simple, error))
421 validity = async_context->validity;
422 async_context->validity = NULL;
428 cipher_context_encrypt_thread (GSimpleAsyncResult *simple,
430 GCancellable *cancellable)
432 AsyncContext *async_context;
433 GError *error = NULL;
435 async_context = g_simple_async_result_get_op_res_gpointer (simple);
437 camel_cipher_context_encrypt_sync (
438 CAMEL_CIPHER_CONTEXT (object),
439 async_context->userid, async_context->strings,
440 async_context->ipart, async_context->opart,
441 cancellable, &error);
444 g_simple_async_result_take_error (simple, error);
448 cipher_context_encrypt (CamelCipherContext *context,
450 GPtrArray *recipients,
451 CamelMimePart *ipart,
452 CamelMimePart *opart,
454 GCancellable *cancellable,
455 GAsyncReadyCallback callback,
458 GSimpleAsyncResult *simple;
459 AsyncContext *async_context;
462 async_context = g_slice_new0 (AsyncContext);
463 async_context->userid = g_strdup (userid);
464 async_context->strings = g_ptr_array_new ();
465 async_context->ipart = g_object_ref (ipart);
466 async_context->opart = g_object_ref (opart);
468 for (ii = 0; ii < recipients->len; ii++)
470 async_context->strings,
471 g_strdup (recipients->pdata[ii]));
473 simple = g_simple_async_result_new (
474 G_OBJECT (context), callback,
475 user_data, cipher_context_encrypt);
477 g_simple_async_result_set_check_cancellable (simple, cancellable);
479 g_simple_async_result_set_op_res_gpointer (
480 simple, async_context, (GDestroyNotify) async_context_free);
482 g_simple_async_result_run_in_thread (
483 simple, cipher_context_encrypt_thread,
484 io_priority, cancellable);
486 g_object_unref (simple);
490 cipher_context_encrypt_finish (CamelCipherContext *context,
491 GAsyncResult *result,
494 GSimpleAsyncResult *simple;
496 g_return_val_if_fail (
497 g_simple_async_result_is_valid (
498 result, G_OBJECT (context), cipher_context_encrypt), FALSE);
500 simple = G_SIMPLE_ASYNC_RESULT (result);
502 /* Assume success unless a GError is set. */
503 return !g_simple_async_result_propagate_error (simple, error);
507 cipher_context_decrypt_thread (GSimpleAsyncResult *simple,
509 GCancellable *cancellable)
511 AsyncContext *async_context;
512 GError *error = NULL;
514 async_context = g_simple_async_result_get_op_res_gpointer (simple);
516 async_context->validity = camel_cipher_context_decrypt_sync (
517 CAMEL_CIPHER_CONTEXT (object), async_context->ipart,
518 async_context->opart, cancellable, &error);
521 g_simple_async_result_take_error (simple, error);
525 cipher_context_decrypt (CamelCipherContext *context,
526 CamelMimePart *ipart,
527 CamelMimePart *opart,
529 GCancellable *cancellable,
530 GAsyncReadyCallback callback,
533 GSimpleAsyncResult *simple;
534 AsyncContext *async_context;
536 async_context = g_slice_new0 (AsyncContext);
537 async_context->ipart = g_object_ref (ipart);
538 async_context->opart = g_object_ref (opart);
540 simple = g_simple_async_result_new (
541 G_OBJECT (context), callback,
542 user_data, cipher_context_decrypt);
544 g_simple_async_result_set_check_cancellable (simple, cancellable);
546 g_simple_async_result_set_op_res_gpointer (
547 simple, async_context, (GDestroyNotify) async_context_free);
549 g_simple_async_result_run_in_thread (
550 simple, cipher_context_decrypt_thread,
551 io_priority, cancellable);
553 g_object_unref (simple);
556 static CamelCipherValidity *
557 cipher_context_decrypt_finish (CamelCipherContext *context,
558 GAsyncResult *result,
561 GSimpleAsyncResult *simple;
562 AsyncContext *async_context;
563 CamelCipherValidity *validity;
565 g_return_val_if_fail (
566 g_simple_async_result_is_valid (
567 result, G_OBJECT (context), cipher_context_decrypt), NULL);
569 simple = G_SIMPLE_ASYNC_RESULT (result);
570 async_context = g_simple_async_result_get_op_res_gpointer (simple);
572 if (g_simple_async_result_propagate_error (simple, error))
575 validity = async_context->validity;
576 async_context->validity = NULL;
582 cipher_context_import_keys_thread (GSimpleAsyncResult *simple,
584 GCancellable *cancellable)
586 AsyncContext *async_context;
587 GError *error = NULL;
589 async_context = g_simple_async_result_get_op_res_gpointer (simple);
591 camel_cipher_context_import_keys_sync (
592 CAMEL_CIPHER_CONTEXT (object), async_context->stream,
593 cancellable, &error);
596 g_simple_async_result_take_error (simple, error);
600 cipher_context_import_keys (CamelCipherContext *context,
601 CamelStream *istream,
603 GCancellable *cancellable,
604 GAsyncReadyCallback callback,
607 GSimpleAsyncResult *simple;
608 AsyncContext *async_context;
610 async_context = g_slice_new0 (AsyncContext);
611 async_context->stream = g_object_ref (istream);
613 simple = g_simple_async_result_new (
614 G_OBJECT (context), callback,
615 user_data, cipher_context_import_keys);
617 g_simple_async_result_set_check_cancellable (simple, cancellable);
619 g_simple_async_result_set_op_res_gpointer (
620 simple, async_context, (GDestroyNotify) async_context_free);
622 g_simple_async_result_run_in_thread (
623 simple, cipher_context_import_keys_thread,
624 io_priority, cancellable);
626 g_object_unref (simple);
630 cipher_context_import_keys_finish (CamelCipherContext *context,
631 GAsyncResult *result,
634 GSimpleAsyncResult *simple;
636 g_return_val_if_fail (
637 g_simple_async_result_is_valid (
638 result, G_OBJECT (context),
639 cipher_context_import_keys), FALSE);
641 simple = G_SIMPLE_ASYNC_RESULT (result);
643 /* Assume success unless a GError is set. */
644 return !g_simple_async_result_propagate_error (simple, error);
648 cipher_context_export_keys_thread (GSimpleAsyncResult *simple,
650 GCancellable *cancellable)
652 AsyncContext *async_context;
653 GError *error = NULL;
655 async_context = g_simple_async_result_get_op_res_gpointer (simple);
657 camel_cipher_context_export_keys_sync (
658 CAMEL_CIPHER_CONTEXT (object), async_context->strings,
659 async_context->stream, cancellable, &error);
662 g_simple_async_result_take_error (simple, error);
666 cipher_context_export_keys (CamelCipherContext *context,
668 CamelStream *ostream,
670 GCancellable *cancellable,
671 GAsyncReadyCallback callback,
674 GSimpleAsyncResult *simple;
675 AsyncContext *async_context;
678 async_context = g_slice_new0 (AsyncContext);
679 async_context->strings = g_ptr_array_new ();
680 async_context->stream = g_object_ref (ostream);
682 for (ii = 0; ii < keys->len; ii++)
684 async_context->strings,
685 g_strdup (keys->pdata[ii]));
687 simple = g_simple_async_result_new (
688 G_OBJECT (context), callback,
689 user_data, cipher_context_export_keys);
691 g_simple_async_result_set_check_cancellable (simple, cancellable);
693 g_simple_async_result_set_op_res_gpointer (
694 simple, async_context, (GDestroyNotify) async_context_free);
696 g_simple_async_result_run_in_thread (
697 simple, cipher_context_export_keys_thread,
698 io_priority, cancellable);
700 g_object_unref (simple);
704 cipher_context_export_keys_finish (CamelCipherContext *context,
705 GAsyncResult *result,
708 GSimpleAsyncResult *simple;
710 g_return_val_if_fail (
711 g_simple_async_result_is_valid (
712 result, G_OBJECT (context),
713 cipher_context_export_keys), FALSE);
715 simple = G_SIMPLE_ASYNC_RESULT (result);
717 /* Assume success unless a GError is set. */
718 return !g_simple_async_result_propagate_error (simple, error);
722 camel_cipher_context_class_init (CamelCipherContextClass *class)
724 GObjectClass *object_class;
726 g_type_class_add_private (class, sizeof (CamelCipherContextPrivate));
728 object_class = G_OBJECT_CLASS (class);
729 object_class->set_property = cipher_context_set_property;
730 object_class->get_property = cipher_context_get_property;
731 object_class->dispose = cipher_context_dispose;
732 object_class->finalize = cipher_context_finalize;
734 class->hash_to_id = cipher_context_hash_to_id;
735 class->id_to_hash = cipher_context_id_to_hash;
737 class->sign_sync = cipher_context_sign_sync;
738 class->verify_sync = cipher_context_verify_sync;
739 class->encrypt_sync = cipher_context_encrypt_sync;
740 class->decrypt_sync = cipher_context_decrypt_sync;
741 class->import_keys_sync = cipher_context_import_keys_sync;
742 class->export_keys_sync = cipher_context_export_keys_sync;
744 class->sign = cipher_context_sign;
745 class->sign_finish = cipher_context_sign_finish;
746 class->verify = cipher_context_verify;
747 class->verify_finish = cipher_context_verify_finish;
748 class->encrypt = cipher_context_encrypt;
749 class->encrypt_finish = cipher_context_encrypt_finish;
750 class->decrypt = cipher_context_decrypt;
751 class->decrypt_finish = cipher_context_decrypt_finish;
752 class->import_keys = cipher_context_import_keys;
753 class->import_keys_finish = cipher_context_import_keys_finish;
754 class->export_keys = cipher_context_export_keys;
755 class->export_keys_finish = cipher_context_export_keys_finish;
757 g_object_class_install_property (
760 g_param_spec_object (
766 G_PARAM_CONSTRUCT_ONLY));
770 camel_cipher_context_init (CamelCipherContext *context)
772 context->priv = CAMEL_CIPHER_CONTEXT_GET_PRIVATE (context);
773 g_mutex_init (&context->priv->lock);
777 * camel_cipher_context_sign_sync:
778 * @context: a #CamelCipherContext
779 * @userid: a private key to use to sign the stream
780 * @hash: preferred Message-Integrity-Check hash algorithm
781 * @ipart: input #CamelMimePart
782 * @opart: output #CamelMimePart
783 * @cancellable: optional #GCancellable object, or %NULL
784 * @error: return location for a #GError, or %NULL
786 * Converts the (unsigned) part @ipart into a new self-contained MIME
787 * part @opart. This may be a multipart/signed part, or a simple part
788 * for enveloped types.
790 * Returns: %TRUE on success, %FALSE on error
795 camel_cipher_context_sign_sync (CamelCipherContext *context,
797 CamelCipherHash hash,
798 CamelMimePart *ipart,
799 CamelMimePart *opart,
800 GCancellable *cancellable,
803 CamelCipherContextClass *class;
806 g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), FALSE);
808 class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
809 g_return_val_if_fail (class->sign_sync != NULL, FALSE);
811 CIPHER_LOCK (context);
813 /* Check for cancellation after locking. */
814 if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
815 CIPHER_UNLOCK (context);
819 camel_operation_push_message (cancellable, _("Signing message"));
821 success = class->sign_sync (
822 context, userid, hash, ipart, opart, cancellable, error);
823 CAMEL_CHECK_GERROR (context, sign_sync, success, error);
825 camel_operation_pop_message (cancellable);
827 CIPHER_UNLOCK (context);
833 * camel_cipher_context_sign:
834 * @context: a #CamelCipherContext
835 * @userid: a private key to use to sign the stream
836 * @hash: preferred Message-Integrity-Check hash algorithm
837 * @ipart: input #CamelMimePart
838 * @opart: output #CamelMimePart
839 * @io_priority: the I/O priority of the request
840 * @cancellable: optional #GCancellable object, or %NULL
841 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
842 * @user_data: data to pass to the callback function
844 * Asynchronously converts the (unsigned) part @ipart into a new
845 * self-contained MIME part @opart. This may be a multipart/signed part,
846 * or a simple part for enveloped types.
848 * When the operation is finished, @callback will be called. You can then
849 * call camel_cipher_context_sign_finish() to get the result of the operation.
854 camel_cipher_context_sign (CamelCipherContext *context,
856 CamelCipherHash hash,
857 CamelMimePart *ipart,
858 CamelMimePart *opart,
860 GCancellable *cancellable,
861 GAsyncReadyCallback callback,
864 CamelCipherContextClass *class;
866 g_return_if_fail (CAMEL_IS_CIPHER_CONTEXT (context));
868 class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
869 g_return_if_fail (class->sign != NULL);
872 context, userid, hash, ipart, opart, io_priority,
873 cancellable, callback, user_data);
877 * camel_cipher_context_sign_finish:
878 * @context: a #CamelCipherContext
879 * @result: a #GAsyncResult
880 * @error: return location for a #GError, or %NULL
882 * Finishes the operation started with camel_cipher_context_sign().
884 * Returns: %TRUE on success, %FALSE on error
889 camel_cipher_context_sign_finish (CamelCipherContext *context,
890 GAsyncResult *result,
893 CamelCipherContextClass *class;
895 g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), FALSE);
896 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
898 class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
899 g_return_val_if_fail (class->sign_finish != NULL, FALSE);
901 return class->sign_finish (context, result, error);
905 * camel_cipher_context_verify_sync:
906 * @context: a #CamelCipherContext
907 * @ipart: the #CamelMimePart to verify
908 * @cancellable: optional #GCancellable object, or %NULL
909 * @error: return location for a #GError, or %NULL
911 * Verifies the signature.
913 * Returns: a #CamelCipherValidity structure containing information
914 * about the integrity of the input stream, or %NULL on failure to
917 CamelCipherValidity *
918 camel_cipher_context_verify_sync (CamelCipherContext *context,
919 CamelMimePart *ipart,
920 GCancellable *cancellable,
923 CamelCipherContextClass *class;
924 CamelCipherValidity *valid;
926 g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), NULL);
927 g_return_val_if_fail (CAMEL_IS_MIME_PART (ipart), NULL);
929 class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
930 g_return_val_if_fail (class->verify_sync != NULL, NULL);
932 CIPHER_LOCK (context);
934 /* Check for cancellation after locking. */
935 if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
936 CIPHER_UNLOCK (context);
940 valid = class->verify_sync (context, ipart, cancellable, error);
941 CAMEL_CHECK_GERROR (context, verify_sync, valid != NULL, error);
943 CIPHER_UNLOCK (context);
949 * camel_cipher_context_verify:
950 * @context: a #CamelCipherContext
951 * @ipart: the #CamelMimePart to verify
952 * @io_priority: the I/O priority of the request
953 * @cancellable: optional #GCancellable object, or %NULL
954 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
955 * @user_data: data to pass to the callback function
957 * Asynchronously verifies the signature.
959 * When the operation is finished, @callback will be called. You can
960 * then call camel_cipher_context_verify_finish() to get the result of
966 camel_cipher_context_verify (CamelCipherContext *context,
967 CamelMimePart *ipart,
969 GCancellable *cancellable,
970 GAsyncReadyCallback callback,
973 CamelCipherContextClass *class;
975 g_return_if_fail (CAMEL_IS_CIPHER_CONTEXT (context));
976 g_return_if_fail (CAMEL_IS_MIME_PART (ipart));
978 class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
979 g_return_if_fail (class->verify != NULL);
982 context, ipart, io_priority,
983 cancellable, callback, user_data);
987 * camel_cipher_context_verify_finish:
988 * @context: a #CamelCipherContext
989 * @result: a #GAsyncResult
990 * @error: return location for a #GError, or %NULL
992 * Finishes the operation started with camel_cipher_context_verify().
994 * Returns: a #CamelCipherValidity structure containing information
995 * about the integrity of the input stream, or %NULL on failure to
1000 CamelCipherValidity *
1001 camel_cipher_context_verify_finish (CamelCipherContext *context,
1002 GAsyncResult *result,
1005 CamelCipherContextClass *class;
1007 g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), NULL);
1008 g_return_val_if_fail (G_IS_ASYNC_RESULT (context), NULL);
1010 class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
1011 g_return_val_if_fail (class->verify_finish != NULL, NULL);
1013 return class->verify_finish (context, result, error);
1017 * camel_cipher_context_encrypt_sync:
1018 * @context: a #CamelCipherContext
1019 * @userid: key ID (or email address) to use when signing, or %NULL to not sign
1020 * @recipients: an array of recipient key IDs and/or email addresses
1021 * @ipart: clear-text #CamelMimePart
1022 * @opart: cipher-text #CamelMimePart
1023 * @cancellable: optional #GCancellable object, or %NULL
1024 * @error: return location for a #GError, or %NULL
1026 * Encrypts (and optionally signs) the clear-text @ipart and writes the
1027 * resulting cipher-text to @opart.
1029 * Returns: %TRUE on success, %FALSE on error
1034 camel_cipher_context_encrypt_sync (CamelCipherContext *context,
1035 const gchar *userid,
1036 GPtrArray *recipients,
1037 CamelMimePart *ipart,
1038 CamelMimePart *opart,
1039 GCancellable *cancellable,
1042 CamelCipherContextClass *class;
1045 g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), FALSE);
1046 g_return_val_if_fail (CAMEL_IS_MIME_PART (ipart), FALSE);
1047 g_return_val_if_fail (CAMEL_IS_MIME_PART (opart), FALSE);
1049 class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
1050 g_return_val_if_fail (class->encrypt_sync != NULL, FALSE);
1052 CIPHER_LOCK (context);
1054 /* Check for cancellation after locking. */
1055 if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
1056 CIPHER_UNLOCK (context);
1060 camel_operation_push_message (cancellable, _("Encrypting message"));
1062 success = class->encrypt_sync (
1063 context, userid, recipients,
1064 ipart, opart, cancellable, error);
1065 CAMEL_CHECK_GERROR (context, encrypt_sync, success, error);
1067 camel_operation_pop_message (cancellable);
1069 CIPHER_UNLOCK (context);
1075 * camel_cipher_context_encrypt:
1076 * @context: a #CamelCipherContext
1077 * @userid: key id (or email address) to use when signing, or %NULL to not sign
1078 * @recipients: an array of recipient key IDs and/or email addresses
1079 * @ipart: clear-text #CamelMimePart
1080 * @opart: cipher-text #CamelMimePart
1081 * @io_priority: the I/O priority of the request
1082 * @cancellable: optional #GCancellable object, or %NULL
1083 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
1084 * @user_data: data to pass to the callback function
1086 * Asynchronously encrypts (and optionally signs) the clear-text @ipart and
1087 * writes the resulting cipher-text to @opart.
1089 * When the operation is finished, @callback will be called. You can
1090 * then call camel_cipher_context_encrypt_finish() to get the result of
1096 camel_cipher_context_encrypt (CamelCipherContext *context,
1097 const gchar *userid,
1098 GPtrArray *recipients,
1099 CamelMimePart *ipart,
1100 CamelMimePart *opart,
1102 GCancellable *cancellable,
1103 GAsyncReadyCallback callback,
1106 CamelCipherContextClass *class;
1108 g_return_if_fail (CAMEL_IS_CIPHER_CONTEXT (context));
1109 g_return_if_fail (CAMEL_IS_MIME_PART (ipart));
1110 g_return_if_fail (CAMEL_IS_MIME_PART (opart));
1112 class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
1113 g_return_if_fail (class->encrypt != NULL);
1116 context, userid, recipients, ipart, opart,
1117 io_priority, cancellable, callback, user_data);
1121 * camel_cipher_context_encrypt_finish:
1122 * @context: a #CamelCipherContext
1123 * @result: a #GAsyncResult
1124 * @error: return location for a #GError, or %NULL
1126 * Finishes the operation started with camel_cipher_context_encrypt().
1128 * Returns: %TRUE on success, %FALSE on error
1133 camel_cipher_context_encrypt_finish (CamelCipherContext *context,
1134 GAsyncResult *result,
1137 CamelCipherContextClass *class;
1139 g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), FALSE);
1140 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
1142 class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
1143 g_return_val_if_fail (class->encrypt_finish != NULL, FALSE);
1145 return class->encrypt_finish (context, result, error);
1149 * camel_cipher_context_decrypt_sync:
1150 * @context: a #CamelCipherContext
1151 * @ipart: cipher-text #CamelMimePart
1152 * @opart: clear-text #CamelMimePart
1153 * @cancellable: optional #GCancellable object, or %NULL
1154 * @error: return location for a #GError, or %NULL
1156 * Decrypts @ipart into @opart.
1158 * Returns: a validity/encryption status, or %NULL on error
1162 CamelCipherValidity *
1163 camel_cipher_context_decrypt_sync (CamelCipherContext *context,
1164 CamelMimePart *ipart,
1165 CamelMimePart *opart,
1166 GCancellable *cancellable,
1169 CamelCipherContextClass *class;
1170 CamelCipherValidity *valid;
1172 g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), NULL);
1173 g_return_val_if_fail (CAMEL_IS_MIME_PART (ipart), NULL);
1174 g_return_val_if_fail (CAMEL_IS_MIME_PART (opart), NULL);
1176 class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
1177 g_return_val_if_fail (class->decrypt_sync != NULL, NULL);
1179 CIPHER_LOCK (context);
1181 /* Check for cancellation after locking. */
1182 if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
1183 CIPHER_UNLOCK (context);
1187 camel_operation_push_message (cancellable, _("Decrypting message"));
1189 valid = class->decrypt_sync (
1190 context, ipart, opart, cancellable, error);
1191 CAMEL_CHECK_GERROR (context, decrypt_sync, valid != NULL, error);
1193 camel_operation_pop_message (cancellable);
1195 CIPHER_UNLOCK (context);
1201 * camel_cipher_context_decrypt:
1202 * @context: a #CamelCipherContext
1203 * @ipart: cipher-text #CamelMimePart
1204 * @opart: clear-text #CamelMimePart
1205 * @io_priority: the I/O priority of the request
1206 * @cancellable: optional #GCancellable object, or %NULL
1207 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
1208 * @user_data: data to pass to the callback function
1210 * Asynchronously decrypts @ipart into @opart.
1212 * When the operation is finished, @callback will be called. You can
1213 * then call camel_cipher_context_decrypt_finish() to get the result of
1219 camel_cipher_context_decrypt (CamelCipherContext *context,
1220 CamelMimePart *ipart,
1221 CamelMimePart *opart,
1223 GCancellable *cancellable,
1224 GAsyncReadyCallback callback,
1227 CamelCipherContextClass *class;
1229 g_return_if_fail (CAMEL_IS_CIPHER_CONTEXT (context));
1230 g_return_if_fail (CAMEL_IS_MIME_PART (ipart));
1231 g_return_if_fail (CAMEL_IS_MIME_PART (opart));
1233 class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
1234 g_return_if_fail (class->decrypt != NULL);
1237 context, ipart, opart, io_priority,
1238 cancellable, callback, user_data);
1242 * camel_cipher_context_decrypt_finish:
1243 * @context: a #CamelCipherContext
1244 * @result: a #GAsyncResult
1245 * @error: return location for a #GError, or %NULL
1247 * Finishes the operation started with camel_cipher_context_decrypt().
1249 * Returns: a validity/encryption status, or %NULL on error
1253 CamelCipherValidity *
1254 camel_cipher_context_decrypt_finish (CamelCipherContext *context,
1255 GAsyncResult *result,
1258 CamelCipherContextClass *class;
1260 g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), NULL);
1261 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
1263 class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
1264 g_return_val_if_fail (class->decrypt_finish != NULL, NULL);
1266 return class->decrypt_finish (context, result, error);
1270 * camel_cipher_context_import_keys_sync:
1271 * @context: a #CamelCipherContext
1272 * @istream: an input stream containing keys
1273 * @cancellable: optional #GCancellable object, or %NULL
1274 * @error: return location for a #GError, or %NULL
1276 * Imports a stream of keys/certificates contained within @istream
1277 * into the key/certificate database controlled by @context.
1279 * Returns: %TRUE on success, %FALSE on error
1284 camel_cipher_context_import_keys_sync (CamelCipherContext *context,
1285 CamelStream *istream,
1286 GCancellable *cancellable,
1289 CamelCipherContextClass *class;
1292 g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), FALSE);
1293 g_return_val_if_fail (CAMEL_IS_STREAM (istream), FALSE);
1295 class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
1296 g_return_val_if_fail (class->import_keys_sync != NULL, FALSE);
1298 success = class->import_keys_sync (
1299 context, istream, cancellable, error);
1300 CAMEL_CHECK_GERROR (context, import_keys_sync, success, error);
1306 * camel_cipher_context_import_keys:
1307 * @context: a #CamelCipherContext
1308 * @istream: an input stream containing keys
1309 * @io_priority: the I/O priority of the request
1310 * @cancellable: optional #GCancellable object, or %NULL
1311 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
1312 * @user_data: data to pass to the callback function
1314 * Asynchronously imports a stream of keys/certificates contained within
1315 * @istream into the key/certificate database controlled by @context.
1317 * When the operation is finished, @callback will be called. You can
1318 * then call camel_cipher_context_import_keys_finish() to get the result
1324 camel_cipher_context_import_keys (CamelCipherContext *context,
1325 CamelStream *istream,
1327 GCancellable *cancellable,
1328 GAsyncReadyCallback callback,
1331 CamelCipherContextClass *class;
1333 g_return_if_fail (CAMEL_IS_CIPHER_CONTEXT (context));
1334 g_return_if_fail (CAMEL_IS_STREAM (istream));
1336 class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
1337 g_return_if_fail (class->import_keys != NULL);
1339 class->import_keys (
1340 context, istream, io_priority,
1341 cancellable, callback, user_data);
1345 * camel_cipher_context_import_keys_finish:
1346 * @context: a #CamelCipherContext
1347 * @result: a #GAsyncResult
1348 * @error: return location for a #GError, or %NULL
1350 * Finishes the operation started with camel_cipher_context_import_keys().
1352 * Returns: %TRUE on success, %FALSE on error
1357 camel_cipher_context_import_keys_finish (CamelCipherContext *context,
1358 GAsyncResult *result,
1361 CamelCipherContextClass *class;
1363 g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), FALSE);
1364 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
1366 class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
1367 g_return_val_if_fail (class->import_keys_finish != NULL, FALSE);
1369 return class->import_keys_finish (context, result, error);
1373 * camel_cipher_context_export_keys_sync:
1374 * @context: a #CamelCipherContext
1375 * @keys: an array of key IDs
1376 * @ostream: an output stream
1377 * @cancellable: optional #GCancellable object, or %NULL
1378 * @error: return location for a #GError, or %NULL
1380 * Exports the keys/certificates in @keys to the stream @ostream from
1381 * the key/certificate database controlled by @context.
1383 * Returns: %TRUE on success, %FALSE on error
1388 camel_cipher_context_export_keys_sync (CamelCipherContext *context,
1390 CamelStream *ostream,
1391 GCancellable *cancellable,
1394 CamelCipherContextClass *class;
1397 g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), FALSE);
1398 g_return_val_if_fail (keys != NULL, FALSE);
1399 g_return_val_if_fail (CAMEL_IS_STREAM (ostream), FALSE);
1401 class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
1402 g_return_val_if_fail (class->export_keys_sync != NULL, FALSE);
1404 success = class->export_keys_sync (
1405 context, keys, ostream, cancellable, error);
1406 CAMEL_CHECK_GERROR (context, export_keys_sync, success, error);
1412 * camel_cipher_context_export_keys:
1413 * @context: a #CamelCipherContext
1414 * @keys: an array of key IDs
1415 * @ostream: an output stream
1416 * @io_priority: the I/O priority of the request
1417 * @cancellable: optional #GCancellable object, or %NULL
1418 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
1419 * @user_data: data to pass to the callback function
1421 * Asynchronously exports the keys/certificates in @keys to the stream
1422 * @ostream from the key/certificate database controlled by @context.
1424 * When the operation is finished, @callback will be called. You can then
1425 * call camel_cipher_context_export_keys_finish() to get the result of the
1431 camel_cipher_context_export_keys (CamelCipherContext *context,
1433 CamelStream *ostream,
1435 GCancellable *cancellable,
1436 GAsyncReadyCallback callback,
1439 CamelCipherContextClass *class;
1441 g_return_if_fail (CAMEL_IS_CIPHER_CONTEXT (context));
1442 g_return_if_fail (keys != NULL);
1443 g_return_if_fail (CAMEL_IS_STREAM (ostream));
1445 class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
1446 g_return_if_fail (class->export_keys != NULL);
1448 class->export_keys (
1449 context, keys, ostream, io_priority,
1450 cancellable, callback, user_data);
1454 * camel_cipher_context_export_keys_finish:
1455 * @context: a #CamelCipherContext
1456 * @result: a #GAsyncResult
1457 * @error: return location for a #GError, or %NULL
1459 * Finishes the operation started with camel_cipher_context_export_keys().
1461 * Returns: %TRUE on success, %FALSE on error
1466 camel_cipher_context_export_keys_finish (CamelCipherContext *context,
1467 GAsyncResult *result,
1470 CamelCipherContextClass *class;
1472 g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), FALSE);
1473 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
1475 class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
1476 g_return_val_if_fail (class->export_keys_finish != NULL, FALSE);
1478 return class->export_keys_finish (context, result, error);
1481 /* a couple of util functions */
1483 camel_cipher_context_id_to_hash (CamelCipherContext *context,
1486 CamelCipherContextClass *class;
1488 g_return_val_if_fail (
1489 CAMEL_IS_CIPHER_CONTEXT (context),
1490 CAMEL_CIPHER_HASH_DEFAULT);
1492 class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
1493 g_return_val_if_fail (
1494 class->id_to_hash != NULL, CAMEL_CIPHER_HASH_DEFAULT);
1496 return class->id_to_hash (context, id);
1500 camel_cipher_context_hash_to_id (CamelCipherContext *context,
1501 CamelCipherHash hash)
1503 CamelCipherContextClass *class;
1505 g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), NULL);
1507 class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
1508 g_return_val_if_fail (class->hash_to_id != NULL, NULL);
1510 return class->hash_to_id (context, hash);
1513 /* Cipher Validity stuff */
1515 ccv_certinfo_free (CamelCipherCertInfo *info)
1517 g_return_if_fail (info != NULL);
1519 g_free (info->name);
1520 g_free (info->email);
1522 if (info->cert_data && info->cert_data_free)
1523 info->cert_data_free (info->cert_data);
1528 CamelCipherValidity *
1529 camel_cipher_validity_new (void)
1531 CamelCipherValidity *validity;
1533 validity = g_malloc (sizeof (*validity));
1534 camel_cipher_validity_init (validity);
1540 camel_cipher_validity_init (CamelCipherValidity *validity)
1542 g_return_if_fail (validity != NULL);
1544 memset (validity, 0, sizeof (*validity));
1545 g_queue_init (&validity->children);
1546 g_queue_init (&validity->sign.signers);
1547 g_queue_init (&validity->encrypt.encrypters);
1551 camel_cipher_validity_get_valid (CamelCipherValidity *validity)
1553 return validity != NULL
1554 && validity->sign.status == CAMEL_CIPHER_VALIDITY_SIGN_GOOD;
1558 camel_cipher_validity_set_valid (CamelCipherValidity *validity,
1561 g_return_if_fail (validity != NULL);
1563 validity->sign.status = valid ? CAMEL_CIPHER_VALIDITY_SIGN_GOOD : CAMEL_CIPHER_VALIDITY_SIGN_BAD;
1567 camel_cipher_validity_get_description (CamelCipherValidity *validity)
1569 g_return_val_if_fail (validity != NULL, NULL);
1571 return validity->sign.description;
1575 camel_cipher_validity_set_description (CamelCipherValidity *validity,
1576 const gchar *description)
1578 g_return_if_fail (validity != NULL);
1580 g_free (validity->sign.description);
1581 validity->sign.description = g_strdup (description);
1585 camel_cipher_validity_clear (CamelCipherValidity *validity)
1587 g_return_if_fail (validity != NULL);
1589 /* TODO: this doesn't free children/clear key lists */
1590 g_free (validity->sign.description);
1591 g_free (validity->encrypt.description);
1592 camel_cipher_validity_init (validity);
1595 CamelCipherValidity *
1596 camel_cipher_validity_clone (CamelCipherValidity *vin)
1598 CamelCipherValidity *vo;
1601 g_return_val_if_fail (vin != NULL, NULL);
1603 vo = camel_cipher_validity_new ();
1604 vo->sign.status = vin->sign.status;
1605 vo->sign.description = g_strdup (vin->sign.description);
1606 vo->encrypt.status = vin->encrypt.status;
1607 vo->encrypt.description = g_strdup (vin->encrypt.description);
1609 head = g_queue_peek_head_link (&vin->sign.signers);
1610 for (link = head; link != NULL; link = g_list_next (link)) {
1611 CamelCipherCertInfo *info = link->data;
1613 if (info->cert_data && info->cert_data_clone && info->cert_data_free)
1614 camel_cipher_validity_add_certinfo_ex (vo, CAMEL_CIPHER_VALIDITY_SIGN, info->name, info->email, info->cert_data_clone (info->cert_data), info->cert_data_free, info->cert_data_clone);
1616 camel_cipher_validity_add_certinfo (vo, CAMEL_CIPHER_VALIDITY_SIGN, info->name, info->email);
1619 head = g_queue_peek_head_link (&vin->encrypt.encrypters);
1620 for (link = head; link != NULL; link = g_list_next (link)) {
1621 CamelCipherCertInfo *info = link->data;
1623 if (info->cert_data && info->cert_data_clone && info->cert_data_free)
1624 camel_cipher_validity_add_certinfo_ex (vo, CAMEL_CIPHER_VALIDITY_SIGN, info->name, info->email, info->cert_data_clone (info->cert_data), info->cert_data_free, info->cert_data_clone);
1626 camel_cipher_validity_add_certinfo (vo, CAMEL_CIPHER_VALIDITY_ENCRYPT, info->name, info->email);
1633 * camel_cipher_validity_add_certinfo:
1639 * Add a cert info to the signer or encrypter info.
1642 camel_cipher_validity_add_certinfo (CamelCipherValidity *vin,
1643 enum _camel_cipher_validity_mode_t mode,
1647 camel_cipher_validity_add_certinfo_ex (vin, mode, name, email, NULL, NULL, NULL);
1651 * camel_cipher_validity_add_certinfo_ex:
1653 * Add a cert info to the signer or encrypter info, with extended data set.
1658 camel_cipher_validity_add_certinfo_ex (CamelCipherValidity *vin,
1659 camel_cipher_validity_mode_t mode,
1663 void (*cert_data_free)(gpointer cert_data),
1664 gpointer (*cert_data_clone)(gpointer cert_data))
1666 CamelCipherCertInfo *info;
1668 g_return_if_fail (vin != NULL);
1670 g_return_if_fail (cert_data_free != NULL);
1671 g_return_if_fail (cert_data_clone != NULL);
1674 info = g_malloc0 (sizeof (*info));
1675 info->name = g_strdup (name);
1676 info->email = g_strdup (email);
1678 info->cert_data = cert_data;
1679 info->cert_data_free = cert_data_free;
1680 info->cert_data_clone = cert_data_clone;
1683 if (mode == CAMEL_CIPHER_VALIDITY_SIGN)
1684 g_queue_push_tail (&vin->sign.signers, info);
1686 g_queue_push_tail (&vin->encrypt.encrypters, info);
1690 * camel_cipher_validity_envelope:
1694 * Calculate a conglomerate validity based on wrapping one secure part inside
1698 camel_cipher_validity_envelope (CamelCipherValidity *parent,
1699 CamelCipherValidity *valid)
1702 g_return_if_fail (parent != NULL);
1703 g_return_if_fail (valid != NULL);
1705 if (parent->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE
1706 && parent->encrypt.status == CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE
1707 && valid->sign.status == CAMEL_CIPHER_VALIDITY_SIGN_NONE
1708 && valid->encrypt.status != CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE) {
1711 /* case 1: only signed inside only encrypted -> merge both */
1712 parent->encrypt.status = valid->encrypt.status;
1713 parent->encrypt.description = g_strdup (valid->encrypt.description);
1715 head = g_queue_peek_head_link (&valid->encrypt.encrypters);
1716 for (link = head; link != NULL; link = g_list_next (link)) {
1717 CamelCipherCertInfo *info = link->data;
1718 camel_cipher_validity_add_certinfo (
1719 parent, CAMEL_CIPHER_VALIDITY_ENCRYPT,
1720 info->name, info->email);
1722 } else if (parent->sign.status == CAMEL_CIPHER_VALIDITY_SIGN_NONE
1723 && parent->encrypt.status != CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE
1724 && valid->sign.status != CAMEL_CIPHER_VALIDITY_SIGN_NONE
1725 && valid->encrypt.status == CAMEL_CIPHER_VALIDITY_ENCRYPT_NONE) {
1728 /* case 2: only encrypted inside only signed */
1729 parent->sign.status = valid->sign.status;
1730 parent->sign.description = g_strdup (valid->sign.description);
1732 head = g_queue_peek_head_link (&valid->sign.signers);
1733 for (link = head; link != NULL; link = g_list_next (link)) {
1734 CamelCipherCertInfo *info = link->data;
1735 camel_cipher_validity_add_certinfo (
1736 parent, CAMEL_CIPHER_VALIDITY_SIGN,
1737 info->name, info->email);
1740 /* Otherwise, I dunno - what do you do? */
1744 camel_cipher_validity_free (CamelCipherValidity *validity)
1746 CamelCipherValidity *child;
1747 CamelCipherCertInfo *info;
1750 if (validity == NULL)
1753 queue = &validity->children;
1754 while ((child = g_queue_pop_head (queue)) != NULL)
1755 camel_cipher_validity_free (child);
1757 queue = &validity->sign.signers;
1758 while ((info = g_queue_pop_head (queue)) != NULL)
1759 ccv_certinfo_free (info);
1761 queue = &validity->encrypt.encrypters;
1762 while ((info = g_queue_pop_head (queue)) != NULL)
1763 ccv_certinfo_free (info);
1765 camel_cipher_validity_clear (validity);
1769 /* ********************************************************************** */
1772 * camel_cipher_context_new:
1773 * @session: a #CamelSession
1775 * This creates a new CamelCipherContext object which is used to sign,
1776 * verify, encrypt and decrypt streams.
1778 * Returns: the new CamelCipherContext
1780 CamelCipherContext *
1781 camel_cipher_context_new (CamelSession *session)
1783 g_return_val_if_fail (session != NULL, NULL);
1785 return g_object_new (
1786 CAMEL_TYPE_CIPHER_CONTEXT,
1787 "session", session, NULL);
1791 * camel_cipher_context_get_session:
1792 * @context: a #CamelCipherContext
1797 camel_cipher_context_get_session (CamelCipherContext *context)
1799 g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), NULL);
1801 return context->priv->session;
1804 /* See rfc3156, section 2 and others */
1805 /* We do this simply: Anything not base64 must be qp
1806 * This is so that we can safely translate any occurance of "From "
1807 * into the quoted-printable escaped version safely. */
1809 cc_prepare_sign (CamelMimePart *part)
1811 CamelDataWrapper *dw;
1812 CamelTransferEncoding encoding;
1815 dw = camel_medium_get_content ((CamelMedium *) part);
1819 /* should not change encoding for these, they have the right encoding set already */
1820 if (CAMEL_IS_MULTIPART_SIGNED (dw) || CAMEL_IS_MULTIPART_ENCRYPTED (dw))
1823 if (CAMEL_IS_MULTIPART (dw)) {
1824 parts = camel_multipart_get_number ((CamelMultipart *) dw);
1825 for (i = 0; i < parts; i++)
1826 cc_prepare_sign (camel_multipart_get_part ((CamelMultipart *) dw, i));
1827 } else if (CAMEL_IS_MIME_MESSAGE (dw)) {
1828 cc_prepare_sign ((CamelMimePart *) dw);
1830 encoding = camel_mime_part_get_encoding (part);
1832 if (encoding != CAMEL_TRANSFER_ENCODING_BASE64
1833 && encoding != CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE) {
1834 camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE);
1840 * camel_cipher_canonical_to_stream:
1841 * @part: Part to write.
1842 * @flags: flags for the canonicalisation filter (CamelMimeFilterCanon)
1843 * @ostream: stream to write canonicalised output to.
1844 * @cancellable: optional #GCancellable object, or %NULL
1845 * @error: return location for a #GError, or %NULL
1847 * Writes a part to a stream in a canonicalised format, suitable for signing/encrypting.
1849 * The transfer encoding paramaters for the part may be changed by this function.
1851 * Returns: -1 on error;
1854 camel_cipher_canonical_to_stream (CamelMimePart *part,
1856 CamelStream *ostream,
1857 GCancellable *cancellable,
1860 CamelStream *filter;
1861 CamelMimeFilter *canon;
1864 g_return_val_if_fail (CAMEL_IS_MIME_PART (part), -1);
1865 g_return_val_if_fail (CAMEL_IS_STREAM (ostream), -1);
1867 if (flags & (CAMEL_MIME_FILTER_CANON_FROM | CAMEL_MIME_FILTER_CANON_STRIP))
1868 cc_prepare_sign (part);
1870 filter = camel_stream_filter_new (ostream);
1871 canon = camel_mime_filter_canon_new (flags);
1872 camel_stream_filter_add (CAMEL_STREAM_FILTER (filter), canon);
1873 g_object_unref (canon);
1875 if (camel_data_wrapper_write_to_stream_sync (
1876 CAMEL_DATA_WRAPPER (part), filter, cancellable, error) != -1
1877 && camel_stream_flush (filter, cancellable, error) != -1)
1880 g_object_unref (filter);
1882 /* Reset stream position to beginning. */
1883 if (G_IS_SEEKABLE (ostream))
1885 G_SEEKABLE (ostream), 0,
1886 G_SEEK_SET, NULL, NULL);