diff options
-rw-r--r-- | camel/ChangeLog | 13 | ||||
-rw-r--r-- | camel/Makefile.am | 2 | ||||
-rw-r--r-- | camel/camel-pgp-context.c | 1359 | ||||
-rw-r--r-- | camel/camel-pgp-context.h | 70 | ||||
-rw-r--r-- | camel/camel-pgp-mime.c | 504 | ||||
-rw-r--r-- | camel/camel-pgp-mime.h | 26 | ||||
-rw-r--r-- | camel/camel.h | 1 |
7 files changed, 41 insertions, 1934 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index c255d7d83b..1fe9952613 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,5 +1,18 @@ 2002-06-26 Jeffrey Stedfast <fejj@ximian.com> + * camel-pgp-context.[c,h]: Removed. + + * camel-pgp-mime.c (pgp_mime_part_sign_restore_part): Removed. + (pgp_mime_part_sign_prepare_part): Removed. + (camel_pgp_mime_part_sign): Removed. + (camel_pgp_mime_part_verify): Removed. + (camel_pgp_mime_part_encrypt): Removed. + (camel_pgp_mime_part_decrypt): Removed. + (camel_pgp_mime_is_rfc2015_signed): Documented. + (camel_pgp_mime_is_rfc2015_encrypted): Same. + +2002-06-26 Jeffrey Stedfast <fejj@ximian.com> + * camel-multipart-encrypted.c (camel_multipart_encrypted_encrypt): Oops, this needs to take a userid argument. diff --git a/camel/Makefile.am b/camel/Makefile.am index f1b4cbca2e..71fbe008fa 100644 --- a/camel/Makefile.am +++ b/camel/Makefile.am @@ -73,7 +73,6 @@ libcamel_la_SOURCES = \ camel-object.c \ camel-operation.c \ camel-partition-table.c \ - camel-pgp-context.c \ camel-pgp-mime.c \ camel-smime-context.c \ camel-smime-utils.c \ @@ -174,7 +173,6 @@ libcamelinclude_HEADERS = \ camel-object.h \ camel-operation.h \ camel-partition-table.h \ - camel-pgp-context.h \ camel-pgp-mime.h \ camel-smime-context.h \ camel-smime-utils.h \ diff --git a/camel/camel-pgp-context.c b/camel/camel-pgp-context.c deleted file mode 100644 index 47e912a903..0000000000 --- a/camel/camel-pgp-context.c +++ /dev/null @@ -1,1359 +0,0 @@ -/* -*- 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 version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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 Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "camel-pgp-context.h" - -#include "camel-stream-fs.h" -#include "camel-stream-mem.h" - -#include "camel-operation.h" - -#include "camel-charset-map.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <errno.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <dirent.h> - -#include <ctype.h> - -#include <signal.h> -#include <sys/ioctl.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <termios.h> -#include <unistd.h> - -#include <ctype.h> - -#include <iconv.h> -#include <gal/unicode/gunicode.h> -#include <gal/util/e-iconv.h> - -#define d(x) - -struct _CamelPgpContextPrivate { - CamelPgpType type; - char *path; -}; - -static int pgp_sign (CamelCipherContext *ctx, const char *userid, CamelCipherHash hash, - CamelStream *istream, CamelStream *ostream, CamelException *ex); -static CamelCipherValidity *pgp_verify (CamelCipherContext *context, CamelCipherHash hash, - 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 const char *pgp_hash_to_id(CamelCipherContext *context, CamelCipherHash hash); -static CamelCipherHash pgp_id_to_hash(CamelCipherContext *context, const char *id); - -static CamelCipherContextClass *parent_class; - -static void -camel_pgp_context_init (CamelPgpContext *context) -{ - CamelCipherContext *ciph = (CamelCipherContext *)context; - - context->priv = g_new0 (struct _CamelPgpContextPrivate, 1); - - ciph->sign_protocol = "application/pgp-signature"; - ciph->encrypt_protocol = "application/pgp-encrypted"; -} - -static void -camel_pgp_context_finalise (CamelObject *o) -{ - CamelPgpContext *context = (CamelPgpContext *)o; - - g_free (context->priv->path); - - g_free (context->priv); -} - -static void -camel_pgp_context_class_init (CamelPgpContextClass *camel_pgp_context_class) -{ - 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->verify = pgp_verify; - camel_cipher_context_class->encrypt = pgp_encrypt; - camel_cipher_context_class->decrypt = pgp_decrypt; - camel_cipher_context_class->hash_to_id = pgp_hash_to_id; - camel_cipher_context_class->id_to_hash = pgp_id_to_hash; -} - -CamelType -camel_pgp_context_get_type (void) -{ - static CamelType type = CAMEL_INVALID_TYPE; - - if (type == CAMEL_INVALID_TYPE) { - type = camel_type_register (camel_cipher_context_get_type (), - "CamelPgpContext", - sizeof (CamelPgpContext), - sizeof (CamelPgpContextClass), - (CamelObjectClassInitFunc) camel_pgp_context_class_init, - NULL, - (CamelObjectInitFunc) camel_pgp_context_init, - (CamelObjectFinalizeFunc) camel_pgp_context_finalise); - } - - return type; -} - - -/** - * camel_pgp_context_new: - * @session: CamelSession - * @type: One of CAMEL_PGP_TYPE_PGP2, PGP5, GPG, or PGP6 - * @path: path to PGP binary - * @remember: Remember the pgp passphrase - * - * This creates a new CamelPgpContext object which is used to sign, - * verify, encrypt and decrypt streams. - * - * Return value: the new CamelPgpContext - **/ -CamelCipherContext * -camel_pgp_context_new (CamelSession *session, CamelPgpType type, const char *path) -{ - CamelPgpContext *context; - - g_return_val_if_fail (session != NULL, NULL); - - if (type == CAMEL_PGP_TYPE_NONE || !path || !*path) - return NULL; - - context = CAMEL_PGP_CONTEXT (camel_object_new (CAMEL_PGP_CONTEXT_TYPE)); - - camel_cipher_context_construct (CAMEL_CIPHER_CONTEXT (context), session); - - context->priv->type = type; - context->priv->path = g_strdup (path); - - return (CamelCipherContext *) context; -} - - - -static const gchar * -pgp_get_type_as_string (CamelPgpType type) -{ - switch (type) { - case CAMEL_PGP_TYPE_PGP2: - return "PGP 2.6.x"; - case CAMEL_PGP_TYPE_PGP5: - return "PGP 5.0"; - case CAMEL_PGP_TYPE_PGP6: - return "PGP 6.5.8"; - case CAMEL_PGP_TYPE_GPG: - return "GnuPG"; - default: - g_assert_not_reached (); - return NULL; - } -} - -static gchar * -pgp_get_passphrase (CamelSession *session, CamelPgpType pgp_type, char *userid) -{ - gchar *passphrase, *prompt; - const char *type; - - type = pgp_get_type_as_string (pgp_type); - - if (userid) - prompt = g_strdup_printf (_("Please enter your %s passphrase for %s"), - type, userid); - else - prompt = g_strdup_printf (_("Please enter your %s passphrase"), - type); - - /* Use the userid as a key if possible, else be generic and use the type */ - passphrase = camel_session_get_password (session, prompt, TRUE, - NULL, userid ? userid : type, - NULL); - g_free (prompt); - - return passphrase; -} - -static void -pgp_forget_passphrase (CamelSession *session, CamelPgpType pgp_type, char *userid) -{ - const char *type = NULL; - - if (!userid) - type = pgp_get_type_as_string (pgp_type); - - camel_session_forget_password (session, NULL, userid ? userid : type, NULL); -} - -static void -pass_free (char *passphrase) -{ - if (passphrase) { - memset (passphrase, 0, strlen (passphrase)); - g_free (passphrase); - } -} - -static int -cleanup_child (pid_t child) -{ - int status; - pid_t wait_result; - sigset_t mask, omask; - - /* PGP5 closes fds before exiting, meaning this might be called - * too early. So wait a bit for the result. - */ - sigemptyset (&mask); - sigaddset (&mask, SIGALRM); - sigprocmask (SIG_BLOCK, &mask, &omask); - alarm (1); - wait_result = waitpid (child, &status, 0); - alarm (0); - sigprocmask (SIG_SETMASK, &omask, NULL); - - if (wait_result == -1 && errno == EINTR) { - /* The child is hanging: send a friendly reminder. */ - kill (child, SIGTERM); - sleep (1); - wait_result = waitpid (child, &status, WNOHANG); - if (wait_result == 0) { - /* Still hanging; use brute force. */ - kill (child, SIGKILL); - sleep (1); - wait_result = waitpid (child, &status, WNOHANG); - } - } - - if (wait_result != -1 && WIFEXITED (status)) - return WEXITSTATUS (status); - else - return -1; -} - -static void -cleanup_before_exec (int fd) -{ - int maxfd, i; - - maxfd = sysconf (_SC_OPEN_MAX); - if (maxfd < 0) - return; - - /* Loop over all fds. */ - for (i = 0; i < maxfd; i++) { - if ((STDIN_FILENO != i) && - (STDOUT_FILENO != i) && - (STDERR_FILENO != i) && - (fd != i)) - close (i); - } -} - -static int -crypto_exec_with_passwd (const char *path, char *argv[], const char *input, int inlen, - int passwd_fds[], const char *passphrase, - char **output, int *outlen, char **diagnostics) -{ - gboolean eof_seen, diag_eof_seen, passwd_eof_seen, input_eof_seen; - size_t passwd_remaining, passwd_incr, input_remaining, input_incr; - size_t size, alloc_size, diag_size, diag_alloc_size; - int select_result, read_len, write_len, cancel_fd; - int fds[6], *ip_fds, *op_fds, *diag_fds; - const char *passwd_next, *input_next; - char *buf = NULL, *diag_buf = NULL; - fd_set fdset, write_fdset; - struct timeval timeout; - size_t tmp_len; - pid_t child; - int i; - - if (camel_operation_cancel_check (NULL)) { - errno = EINTR; - return -1; - } - - for (i = 0; i < 6; i++) - fds[i] = -1; - - ip_fds = fds; - op_fds = fds + 2; - diag_fds = fds + 4; - - if ((pipe (ip_fds) == -1) || (pipe (op_fds) == -1) || (pipe (diag_fds) == -1)) { - *diagnostics = g_strdup_printf ("Couldn't create pipe to %s: %s", - path, g_strerror (errno)); - - for (i = 0; i < 6; i++) - close (fds[i]); - - close (passwd_fds[0]); - close (passwd_fds[1]); - - return -1; - } - - if (!(child = fork ())) { - /* In child */ - - if ((dup2 (ip_fds[0], STDIN_FILENO) < 0 ) || - (dup2 (op_fds[1], STDOUT_FILENO) < 0 ) || - (dup2 (diag_fds[1], STDERR_FILENO) < 0 )) { - _exit (255); - } - - /* Dissociate from evolution-mail's controlling - * terminal so that pgp/gpg won't be able to read from - * it: PGP 2 will fall back to asking for the password - * on /dev/tty if the passed-in password is incorrect. - * This will make that fail rather than hanging. - */ - setsid (); - - /* Close excess fds */ - cleanup_before_exec (passwd_fds[0]); - - execvp (path, argv); - fprintf (stderr, "Could not execute %s: %s\n", argv[0], - g_strerror (errno)); - _exit (255); - } else if (child < 0) { - *diagnostics = g_strdup_printf ("Cannot fork %s: %s", - argv[0], g_strerror (errno)); - return -1; - } - - /* Parent */ - close (ip_fds[0]); - close (op_fds[1]); - close (diag_fds[1]); - close (passwd_fds[0]); - - fcntl (ip_fds[1], F_SETFL, O_NONBLOCK); - fcntl (op_fds[0], F_SETFL, O_NONBLOCK); - fcntl (diag_fds[0], F_SETFL, O_NONBLOCK); - - timeout.tv_sec = 10; /* timeout in seconds */ - timeout.tv_usec = 0; - - size = diag_size = 0; - alloc_size = 4096; - diag_alloc_size = 1024; - eof_seen = diag_eof_seen = FALSE; - - buf = g_malloc (alloc_size); - diag_buf = g_malloc (diag_alloc_size); - - passwd_next = passphrase; - passwd_remaining = passphrase ? strlen (passphrase) : 0; - passwd_incr = fpathconf (passwd_fds[1], _PC_PIPE_BUF); - /* Use a reasonable default value on error. */ - if (passwd_incr <= 0) - passwd_incr = 1024; - passwd_eof_seen = FALSE; - - input_next = input; - input_remaining = inlen; - input_incr = fpathconf (ip_fds[1], _PC_PIPE_BUF); - if (input_incr <= 0) - input_incr = 1024; - input_eof_seen = FALSE; - - cancel_fd = camel_operation_cancel_fd (NULL); - - while (!(eof_seen && diag_eof_seen)) { - int max = 0; - - FD_ZERO (&fdset); - if (!eof_seen) { - FD_SET (op_fds[0], &fdset); - max = op_fds[0]; - } - if (!diag_eof_seen) { - FD_SET (diag_fds[0], &fdset); - max = MAX (max, diag_fds[0]); - } - if (cancel_fd != -1) { - FD_SET (cancel_fd, &fdset); - max = MAX (max, cancel_fd); - } - - FD_ZERO (&write_fdset); - if (!passwd_eof_seen) { - FD_SET (passwd_fds[1], &write_fdset); - max = MAX (max, passwd_fds[1]); - } - if (!input_eof_seen) { - FD_SET (ip_fds[1], &write_fdset); - max = MAX (max, ip_fds[1]); - } - - select_result = select (max + 1, &fdset, &write_fdset, - NULL, &timeout); - - if (select_result < 0) { - if (errno == EINTR) - continue; - break; - } else if (select_result == 0) { - /* timeout */ - break; - } - - if (cancel_fd != -1 && FD_ISSET (cancel_fd, &fdset)) { - /* user-cancelled */ - break; - } - - if (FD_ISSET (op_fds[0], &fdset)) { - /* More output is available. */ - - if (size + 4096 > alloc_size) { - alloc_size += 4096; - buf = g_realloc (buf, alloc_size); - } - read_len = read (op_fds[0], &buf[size], - alloc_size - size - 1); - if (read_len < 0) { - if (errno == EINTR) - continue; - break; - } - if (read_len == 0) - eof_seen = TRUE; - size += read_len; - } - - if (FD_ISSET (diag_fds[0], &fdset) ) { - /* More stderr is available. */ - - if (diag_size + 1024 > diag_alloc_size) { - diag_alloc_size += 1024; - diag_buf = g_realloc (diag_buf, - diag_alloc_size); - } - - read_len = read (diag_fds[0], &diag_buf[diag_size], - diag_alloc_size - diag_size - 1); - if (read_len < 0) { - if (errno == EINTR) - continue; - break; - } - if (read_len == 0) - diag_eof_seen = TRUE; - diag_size += read_len; - } - - if (FD_ISSET (passwd_fds[1], &write_fdset)) { - /* Ready for more password input. */ - - tmp_len = passwd_incr; - if (tmp_len > passwd_remaining) - tmp_len = passwd_remaining; - write_len = write (passwd_fds[1], passwd_next, - tmp_len); - if (write_len < 0) { - if (errno == EINTR) - continue; - break; - } - passwd_next += write_len; - passwd_remaining -= write_len; - if (passwd_remaining == 0) { - close (passwd_fds[1]); - passwd_eof_seen = TRUE; - } - } - - if (FD_ISSET (ip_fds[1], &write_fdset)) { - /* Ready for more ciphertext input. */ - - tmp_len = input_incr; - if (tmp_len > input_remaining) - tmp_len = input_remaining; - write_len = write (ip_fds[1], input_next, tmp_len); - if (write_len < 0) { - if (errno == EINTR) - continue; - break; - } - input_next += write_len; - input_remaining -= write_len; - if (input_remaining == 0 ) { - close (ip_fds[1]); - input_eof_seen = TRUE; - } - } - } - - buf[size] = 0; - diag_buf[diag_size] = 0; - close (op_fds[0]); - close (diag_fds[0]); - - if (!passwd_eof_seen) - close (passwd_fds[1]); - - *output = buf; - if (outlen) - *outlen = size; - *diagnostics = diag_buf; - - return cleanup_child (child); -} - - -/*----------------------------------------------------------------------* - * Public crypto functions - *----------------------------------------------------------------------*/ - -static char * -hash_string (CamelPgpContext *ctx, CamelCipherHash hash) -{ - if (hash == CAMEL_CIPHER_HASH_DEFAULT) - return NULL; - - switch (ctx->priv->type) { - case CAMEL_PGP_TYPE_GPG: - switch (hash) { - case CAMEL_CIPHER_HASH_MD2: - return "MD2"; - case CAMEL_CIPHER_HASH_MD5: - return "MD5"; - case CAMEL_CIPHER_HASH_SHA1: - return "SHA1"; - case CAMEL_CIPHER_HASH_RIPEMD160: - return "RIPEMD160"; - default: - g_assert_not_reached (); - } - break; - case CAMEL_PGP_TYPE_PGP2: - /* FIXME: find a way to specify a hash algorithm for pgp2 */ - return NULL; - case CAMEL_PGP_TYPE_PGP5: - case CAMEL_PGP_TYPE_PGP6: - switch (hash) { - case CAMEL_CIPHER_HASH_MD2: - return "+hashnum=5"; - case CAMEL_CIPHER_HASH_MD5: - return "+hashnum=1"; - case CAMEL_CIPHER_HASH_SHA1: - return "+hashnum=2"; - case CAMEL_CIPHER_HASH_RIPEMD160: - return "+hashnum=3"; - default: - g_assert_not_reached (); - } - break; - default: - g_assert_not_reached (); - break; - } - - return NULL; -} - -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]; - char *ciphertext = NULL; - char *diagnostics = NULL; - char *passphrase = NULL; - char *hash_str = NULL; - int passwd_fds[2]; - char passwd_fd[32]; - int retval, i; - - /* check for the now unsupported pgp 2.6.x type */ - if (context->priv->type == CAMEL_PGP_TYPE_PGP2) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - "PGP 2.6.x is no longer supported."); - return -1; - } - - /* get the plaintext in a form we can use */ - plaintext = g_byte_array_new (); - stream = camel_stream_mem_new (); - camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (stream), plaintext); - camel_stream_write_to_stream (istream, stream); - camel_object_unref (CAMEL_OBJECT (stream)); - - if (!plaintext->len) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot sign this message: no plaintext to sign")); - goto exception; - } - - passphrase = pgp_get_passphrase (ctx->session, context->priv->type, (char *) userid); - if (!passphrase) { - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("Cannot sign this message: no password provided")); - goto exception; - } - - if (pipe (passwd_fds) < 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot sign this message: couldn't create pipe to GPG/PGP: %s"), - g_strerror (errno)); - goto exception; - } - - hash_str = hash_string (context, hash); - - i = 0; - switch (context->priv->type) { - case CAMEL_PGP_TYPE_GPG: - argv[i++] = "gpg"; - - argv[i++] = "--sign"; - argv[i++] = "-b"; - if (hash_str) { - argv[i++] = "--digest-algo"; - argv[i++] = hash_str; - } - - if (userid) { - argv[i++] = "-u"; - argv[i++] = (char *) userid; - } - - argv[i++] = "--verbose"; - argv[i++] = "--no-secmem-warning"; - argv[i++] = "--no-greeting"; - argv[i++] = "--yes"; - argv[i++] = "--always-trust"; - argv[i++] = "--batch"; - - argv[i++] = "--armor"; - - argv[i++] = "--output"; - argv[i++] = "-"; /* output to stdout */ - - argv[i++] = "--passphrase-fd"; - sprintf (passwd_fd, "%d", passwd_fds[0]); - argv[i++] = passwd_fd; - break; - case CAMEL_PGP_TYPE_PGP5: - argv[i++] = "pgps"; - - if (hash_str) - argv[i++] = hash_str; - - if (userid) { - argv[i++] = "-u"; - argv[i++] = (char *) userid; - } - - argv[i++] = "-b"; /* -b means break off (detach) the signature */ - argv[i++] = "-f"; /* -f means act as a unix-style filter */ - argv[i++] = "-v"; /* -v means verbose diagnostic messages */ - argv[i++] = "-z"; /* FIXME: do we want this option!? */ - argv[i++] = "-a"; /* -a means ascii armor */ - argv[i++] = "-o"; /* -o specifies an output stream */ - argv[i++] = "-"; /* ...in this case, stdout */ - - sprintf (passwd_fd, "PGPPASSFD=%d", passwd_fds[0]); - putenv (passwd_fd); - break; - case CAMEL_PGP_TYPE_PGP2: - case CAMEL_PGP_TYPE_PGP6: - argv[i++] = "pgp"; - - if (hash_str) - argv[i++] = hash_str; - - if (userid) { - argv[i++] = "-u"; - argv[i++] = (char *) userid; - } - - argv[i++] = "-f"; /* -f means act as a unix-style filter */ - argv[i++] = "-l"; /* -l means show longer more descriptive diagnostic messages */ - argv[i++] = "-a"; /* -a means ascii armor */ - argv[i++] = "-o"; /* -o specifies an output stream */ - argv[i++] = "-"; /* ...in this case, stdout */ - - argv[i++] = "-sb"; /* create a detached signature */ - sprintf (passwd_fd, "PGPPASSFD=%d", passwd_fds[0]); - putenv (passwd_fd); - break; - default: - g_assert_not_reached (); - break; - } - - argv[i++] = NULL; - - retval = crypto_exec_with_passwd (context->priv->path, argv, - plaintext->data, plaintext->len, - passwd_fds, passphrase, - &ciphertext, NULL, - &diagnostics); - - g_byte_array_free (plaintext, TRUE); - pass_free (passphrase); - - if (retval != 0 || !*ciphertext) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, diagnostics); - g_free (diagnostics); - g_free (ciphertext); - pgp_forget_passphrase (ctx->session, context->priv->type, (char *) userid); - - return -1; - } - - g_free (diagnostics); - - camel_stream_write (ostream, ciphertext, strlen (ciphertext)); - g_free (ciphertext); - - return 0; - - exception: - - g_byte_array_free (plaintext, TRUE); - - if (passphrase) { - pgp_forget_passphrase (ctx->session, context->priv->type, (char *) userid); - pass_free (passphrase); - } - - return -1; -} - - -static char * -swrite (CamelStream *istream) -{ - CamelStream *ostream; - char *template; - int fd; - - template = g_strdup ("/tmp/evolution-pgp.XXXXXX"); - fd = mkstemp (template); - if (fd == -1) { - g_free (template); - return NULL; - } - - ostream = camel_stream_fs_new_with_fd (fd); - camel_stream_write_to_stream (istream, ostream); - camel_object_unref (CAMEL_OBJECT (ostream)); - - return template; -} - - -static CamelCipherValidity * -pgp_verify (CamelCipherContext *ctx, CamelCipherHash hash, CamelStream *istream, - CamelStream *sigstream, CamelException *ex) -{ - CamelPgpContext *context = CAMEL_PGP_CONTEXT (ctx); - CamelCipherValidity *valid = NULL; - GByteArray *plaintext; - CamelStream *stream; - char *argv[20]; - char *cleartext = NULL; - char *diagnostics = NULL; - int passwd_fds[2]; - char *sigfile = NULL; - int retval, i, clearlen; - - /* check for the now unsupported pgp 2.6.x type */ - if (context->priv->type == CAMEL_PGP_TYPE_PGP2) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - "PGP 2.6.x is no longer supported."); - return NULL; - } - - /* get the plaintext in a form we can use */ - plaintext = g_byte_array_new (); - stream = camel_stream_mem_new (); - camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (stream), plaintext); - camel_stream_write_to_stream (istream, stream); - camel_object_unref (CAMEL_OBJECT (stream)); - - if (!plaintext->len) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot verify this message: no plaintext to verify")); - goto exception; - } - - if (pipe (passwd_fds) < 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot verify this message: couldn't create pipe to GPG/PGP: %s"), - g_strerror (errno)); - goto exception; - } - - if (sigstream != NULL) { - /* We are going to verify a detached signature so save - the signature to a temp file. */ - sigfile = swrite (sigstream); - if (!sigfile) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot verify this message: couldn't create temp file: %s"), - g_strerror (errno)); - goto exception; - } - } - - i = 0; - switch (context->priv->type) { - case CAMEL_PGP_TYPE_GPG: - argv[i++] = "gpg"; - - argv[i++] = "--verbose"; - argv[i++] = "--no-secmem-warning"; - argv[i++] = "--no-greeting"; - argv[i++] = "--no-tty"; - if (!camel_session_is_online (ctx->session)) - argv[i++] = "--no-auto-key-retrieve"; - - argv[i++] = "--yes"; - argv[i++] = "--batch"; - - argv[i++] = "--verify"; - - if (sigstream != NULL) - argv[i++] = sigfile; - - argv[i++] = "-"; - break; - case CAMEL_PGP_TYPE_PGP5: - argv[i++] = "pgpv"; - - argv[i++] = "-z"; - - if (sigstream != NULL) - argv[i++] = sigfile; - - argv[i++] = "-f"; - - break; - case CAMEL_PGP_TYPE_PGP2: - case CAMEL_PGP_TYPE_PGP6: - argv[i++] = "pgp"; - - if (sigstream != NULL) - argv[i++] = sigfile; - - argv[i++] = "-f"; - - break; - default: - g_assert_not_reached (); - break; - } - - argv[i++] = NULL; - - clearlen = 0; - retval = crypto_exec_with_passwd (context->priv->path, argv, - plaintext->data, plaintext->len, - passwd_fds, NULL, - &cleartext, &clearlen, - &diagnostics); - - g_byte_array_free (plaintext, TRUE); - - /* cleanup */ - if (sigfile) { - unlink (sigfile); - g_free (sigfile); - } - - valid = camel_cipher_validity_new (); - - if (retval != 0) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, diagnostics); - - camel_cipher_validity_set_valid (valid, FALSE); - } else { - camel_cipher_validity_set_valid (valid, TRUE); - } - - if (diagnostics) { - const char *locale; - char *desc, *outbuf; - size_t inlen, outlen; - iconv_t cd; - - inlen = strlen (diagnostics); - outlen = inlen * 4; - - desc = outbuf = g_new (unsigned char, outlen + 1); - - locale = e_iconv_locale_charset (); - if (!locale) - locale = "iso-8859-1"; - - cd = e_iconv_open ("UTF-8", locale); - if (cd != (iconv_t) -1) { - const char *inbuf; - size_t ret; - - inbuf = diagnostics; - ret = e_iconv (cd, &inbuf, &inlen, &outbuf, &outlen); - if (ret != (size_t) -1) { - e_iconv (cd, NULL, 0, &outbuf, &outlen); - } - e_iconv_close (cd); - - *outbuf = '\0'; - } else { - const char *inptr, *inend; - - g_warning ("CamelPgpContext::pgp_verify: cannot convert from %s to UTF-8", locale); - - inptr = diagnostics; - inend = inptr + inlen; - - while (inptr && inptr < inend && g_unichar_validate (g_utf8_get_char (inptr))) { - *outbuf++ = g_utf8_get_char (inptr) & 0xff; - inptr = g_utf8_next_char (inptr); - } - - *outbuf = '\0'; - } - - camel_cipher_validity_set_description (valid, desc); - g_free (desc); - } - - g_free (diagnostics); - g_free (cleartext); - - return valid; - - exception: - - g_byte_array_free (plaintext, TRUE); - - return NULL; -} - - -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); - GByteArray *plaintext; - CamelStream *stream; - GPtrArray *argv; - int retval, r; - char *ciphertext = NULL; - char *diagnostics = NULL; - int passwd_fds[2]; - char passwd_fd[32]; - char *passphrase = NULL; - - /* check for the now unsupported pgp 2.6.x type */ - if (context->priv->type == CAMEL_PGP_TYPE_PGP2) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - "PGP 2.6.x is no longer supported."); - return -1; - } - - /* get the plaintext in a form we can use */ - plaintext = g_byte_array_new (); - stream = camel_stream_mem_new (); - camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (stream), plaintext); - camel_stream_write_to_stream (istream, stream); - camel_object_unref (CAMEL_OBJECT (stream)); - - if (!plaintext->len) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot encrypt this message: no plaintext to encrypt")); - goto exception; - } - - if (sign) { - /* we only need a passphrase if we intend on signing */ - passphrase = pgp_get_passphrase (ctx->session, context->priv->type, - (char *) userid); - if (!passphrase) { - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("Cannot encrypt this message: no password provided")); - goto exception; - } - } - - if (pipe (passwd_fds) < 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot encrypt this message: couldn't create pipe to GPG/PGP: %s"), - g_strerror (errno)); - - goto exception; - } - - /* check to make sure we have recipients */ - if (recipients->len == 0) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot encrypt this message: no recipients specified")); - - goto exception; - } - - argv = g_ptr_array_new (); - - switch (context->priv->type) { - case CAMEL_PGP_TYPE_GPG: - g_ptr_array_add (argv, "gpg"); - - g_ptr_array_add (argv, "--verbose"); - g_ptr_array_add (argv, "--no-secmem-warning"); - g_ptr_array_add (argv, "--no-greeting"); - g_ptr_array_add (argv, "--yes"); - g_ptr_array_add (argv, "--always-trust"); - g_ptr_array_add (argv, "--batch"); - - g_ptr_array_add (argv, "--armor"); - - for (r = 0; r < recipients->len; r++) { - g_ptr_array_add (argv, "-r"); - g_ptr_array_add (argv, recipients->pdata[r]); - } - - g_ptr_array_add (argv, "--output"); - g_ptr_array_add (argv, "-"); /* output to stdout */ - - g_ptr_array_add (argv, "--encrypt"); - - if (sign) { - g_ptr_array_add (argv, "--sign"); - - g_ptr_array_add (argv, "-u"); - g_ptr_array_add (argv, (char *) userid); - - g_ptr_array_add (argv, "--passphrase-fd"); - sprintf (passwd_fd, "%d", passwd_fds[0]); - g_ptr_array_add (argv, passwd_fd); - } - break; - case CAMEL_PGP_TYPE_PGP5: - g_ptr_array_add (argv, "pgpe"); - - for (r = 0; r < recipients->len; r++) { - g_ptr_array_add (argv, "-r"); - g_ptr_array_add (argv, recipients->pdata[r]); - } - - g_ptr_array_add (argv, "-f"); - g_ptr_array_add (argv, "-z"); - g_ptr_array_add (argv, "-a"); - g_ptr_array_add (argv, "-o"); - g_ptr_array_add (argv, "-"); /* output to stdout */ - - if (sign) { - g_ptr_array_add (argv, "-s"); - - g_ptr_array_add (argv, "-u"); - g_ptr_array_add (argv, (gchar *) userid); - - sprintf (passwd_fd, "PGPPASSFD=%d", passwd_fds[0]); - putenv (passwd_fd); - } - break; - case CAMEL_PGP_TYPE_PGP2: - case CAMEL_PGP_TYPE_PGP6: - g_ptr_array_add (argv, "pgp"); - g_ptr_array_add (argv, "-f"); - g_ptr_array_add (argv, "-e"); - g_ptr_array_add (argv, "-a"); - g_ptr_array_add (argv, "-o"); - g_ptr_array_add (argv, "-"); - - for (r = 0; r < recipients->len; r++) - g_ptr_array_add (argv, recipients->pdata[r]); - - if (sign) { - g_ptr_array_add (argv, "-s"); - - g_ptr_array_add (argv, "-u"); - g_ptr_array_add (argv, (gchar *) userid); - - sprintf (passwd_fd, "PGPPASSFD=%d", passwd_fds[0]); - putenv (passwd_fd); - } - break; - default: - g_assert_not_reached (); - break; - } - - g_ptr_array_add (argv, NULL); - - retval = crypto_exec_with_passwd (context->priv->path, - (char **) argv->pdata, - plaintext->data, plaintext->len, - passwd_fds, passphrase, - &ciphertext, NULL, - &diagnostics); - - g_byte_array_free (plaintext, TRUE); - - pass_free (passphrase); - g_ptr_array_free (argv, TRUE); - - if (retval != 0 || !*ciphertext) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, diagnostics); - g_free (diagnostics); - g_free (ciphertext); - if (sign) - pgp_forget_passphrase (ctx->session, context->priv->type, - (char *) userid); - - return -1; - } - - g_free (diagnostics); - - camel_stream_write (ostream, ciphertext, strlen (ciphertext)); - g_free (ciphertext); - - return 0; - - exception: - - g_byte_array_free (plaintext, TRUE); - - if (sign) { - pass_free (passphrase); - pgp_forget_passphrase (ctx->session, context->priv->type, (char *) userid); - } - - return -1; -} - - -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]; - char *plaintext = NULL; - int plainlen; - char *diagnostics = NULL; - char *passphrase = NULL; - int passwd_fds[2]; - char passwd_fd[32]; - int retval, i; - - /* check for the now unsupported pgp 2.6.x type */ - if (context->priv->type == CAMEL_PGP_TYPE_PGP2) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - "PGP 2.6.x is no longer supported."); - return -1; - } - - /* get the ciphertext in a form we can use */ - ciphertext = g_byte_array_new (); - stream = camel_stream_mem_new (); - camel_stream_mem_set_byte_array (CAMEL_STREAM_MEM (stream), ciphertext); - camel_stream_write_to_stream (istream, stream); - camel_object_unref (CAMEL_OBJECT (stream)); - - if (!ciphertext->len) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot decrypt this message: no ciphertext to decrypt")); - - goto exception; - } - - passphrase = pgp_get_passphrase (ctx->session, context->priv->type, NULL); - if (!passphrase) { - camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, - _("Cannot decrypt this message: no password provided")); - - goto exception; - } - - if (pipe (passwd_fds) < 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Cannot decrypt this message: couldn't create pipe to GPG/PGP: %s"), - g_strerror (errno)); - - goto exception; - } - - i = 0; - switch (context->priv->type) { - case CAMEL_PGP_TYPE_GPG: - argv[i++] = "gpg"; - - argv[i++] = "--verbose"; - argv[i++] = "--no-secmem-warning"; - argv[i++] = "--no-greeting"; - argv[i++] = "--yes"; - argv[i++] = "--batch"; - - if (!camel_session_is_online (ctx->session)) - argv[i++] = "--no-auto-key-retrieve"; - - argv[i++] = "--output"; - argv[i++] = "-"; /* output to stdout */ - - argv[i++] = "--decrypt"; - - argv[i++] = "--passphrase-fd"; - sprintf (passwd_fd, "%d", passwd_fds[0]); - argv[i++] = passwd_fd; - break; - case CAMEL_PGP_TYPE_PGP5: - argv[i++] = "pgpv"; - - argv[i++] = "-f"; - argv[i++] = "+batchmode=1"; - - sprintf (passwd_fd, "PGPPASSFD=%d", passwd_fds[0]); - putenv (passwd_fd); - break; - case CAMEL_PGP_TYPE_PGP2: - case CAMEL_PGP_TYPE_PGP6: - argv[i++] = "pgp"; - - argv[i++] = "-f"; - - sprintf (passwd_fd, "PGPPASSFD=%d", passwd_fds[0]); - putenv (passwd_fd); - break; - default: - g_assert_not_reached (); - break; - } - - argv[i++] = NULL; - - retval = crypto_exec_with_passwd (context->priv->path, argv, - ciphertext->data, ciphertext->len, - passwd_fds, passphrase, - &plaintext, &plainlen, - &diagnostics); - - g_byte_array_free (ciphertext, TRUE); - pass_free (passphrase); - - /* gpg returns '1' if it succeedes in decrypting but can't verify the signature */ - if (retval != 0 || (context->priv->type == CAMEL_PGP_TYPE_GPG && retval == 1) || !*plaintext) { - camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, diagnostics); - g_free (plaintext); - g_free (diagnostics); - - pgp_forget_passphrase (ctx->session, context->priv->type, NULL); - - return -1; - } - - g_free (diagnostics); - - camel_stream_write (ostream, plaintext, plainlen); - g_free (plaintext); - - return 0; - - exception: - - g_byte_array_free (ciphertext, TRUE); - - if (passphrase) { - pgp_forget_passphrase (ctx->session, context->priv->type, NULL); - pass_free (passphrase); - } - - return -1; -} - -/* this has a 1:1 relationship to CamelCipherHash */ -static char *name_table[] = { - "pgp-sha1", /* we use sha1 as the 'default' */ - "pgp-md2", - "pgp-md5", - "pgp-sha1", - "pgp-ripemd160", -}; - -static const char *pgp_hash_to_id(CamelCipherContext *context, CamelCipherHash hash) -{ - /* if we dont know, just use default? */ - if (hash > sizeof(name_table)/sizeof(name_table[0])) - hash = CAMEL_CIPHER_HASH_DEFAULT; - - return name_table[hash]; -} - -static CamelCipherHash pgp_id_to_hash(CamelCipherContext *context, const char *id) -{ - int i; - unsigned char *tmpid, *o; - const char *in; - unsigned char c; - - if (id == NULL) - return CAMEL_CIPHER_HASH_DEFAULT; - - tmpid = alloca(strlen(id)+1); - in = id; - o = tmpid; - while ((c = (unsigned char)*in++)) - *o++ = tolower(c); - - for (i=1;i<sizeof(name_table)/sizeof(name_table[0]);i++) { - if (!strcmp(name_table[i], tmpid)) - return i; - } - - return CAMEL_CIPHER_HASH_DEFAULT; -} diff --git a/camel/camel-pgp-context.h b/camel/camel-pgp-context.h deleted file mode 100644 index 36d91f7007..0000000000 --- a/camel/camel-pgp-context.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- 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 version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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 Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#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" { -#pragma } -#endif /* __cplusplus */ - -#define CAMEL_PGP_CONTEXT_TYPE (camel_pgp_context_get_type ()) -#define CAMEL_PGP_CONTEXT(obj) (CAMEL_CHECK_CAST((obj), CAMEL_PGP_CONTEXT_TYPE, CamelPgpContext)) -#define CAMEL_PGP_CONTEXT_CLASS(k) (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_PGP_CONTEXT_TYPE, CamelPgpContextClass)) -#define CAMEL_IS_PGP_CONTEXT(o) (CAMEL_CHECK_TYPE((o), CAMEL_PGP_CONTEXT_TYPE)) - -typedef enum { - CAMEL_PGP_TYPE_NONE, - CAMEL_PGP_TYPE_PGP2, /* no longer supported */ - CAMEL_PGP_TYPE_PGP5, - CAMEL_PGP_TYPE_PGP6, - CAMEL_PGP_TYPE_GPG -} CamelPgpType; - -typedef struct _CamelPgpContext { - CamelCipherContext parent_object; - - struct _CamelPgpContextPrivate *priv; - -} CamelPgpContext; - -typedef struct _CamelPgpContextClass { - CamelCipherContextClass parent_class; - -} CamelPgpContextClass; - -CamelType camel_pgp_context_get_type (void); - -CamelCipherContext *camel_pgp_context_new (CamelSession *session, CamelPgpType type, - const char *path); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* CAMEL_PGP_CONTEXT_H */ diff --git a/camel/camel-pgp-mime.c b/camel/camel-pgp-mime.c index 51b3d91994..f9d0ea80a9 100644 --- a/camel/camel-pgp-mime.c +++ b/camel/camel-pgp-mime.c @@ -25,28 +25,24 @@ #include <config.h> #endif -#include "camel-pgp-mime.h" -#include "camel-mime-message.h" -#include "camel-mime-filter-from.h" -#include "camel-mime-filter-bestenc.h" -#include "camel-mime-filter-crlf.h" -#include "camel-mime-filter-charset.h" -#include "camel-mime-filter-chomp.h" -#include "camel-stream-filter.h" -#include "camel-stream-null.h" -#include "camel-stream-mem.h" -#include "camel-stream-fs.h" - #include <stdio.h> #include <stdlib.h> #include <string.h> -#define PGPMIME_DEBUG - -#define d(x) x +#include "camel-pgp-mime.h" +#include "camel-mime-message.h" -/** rfc2015/rfc3156 stuff (aka PGP/MIME) *******************************/ +/** + * camel_pgp_mime_is_rfc2015_signed: + * @mime_part: MIME part + * + * Checks that this part is a multipart/signed part following the + * rfc2015 and/or rfc3156 PGP/MIME specifications. + * + * Returns %TRUE if this looks to be a valid PGP/MIME multipart/signed + * part or %FALSE otherwise. + **/ gboolean camel_pgp_mime_is_rfc2015_signed (CamelMimePart *mime_part) { @@ -63,7 +59,7 @@ camel_pgp_mime_is_rfc2015_signed (CamelMimePart *mime_part) type = camel_mime_part_get_content_type (mime_part); if (!header_content_type_is (type, "multipart", "signed")) return FALSE; - + #ifdef ENABLE_PEDANTIC_PGPMIME /* check that we have a protocol param with the value: "application/pgp-signature" */ param = header_content_type_param (type, "protocol"); @@ -99,6 +95,17 @@ camel_pgp_mime_is_rfc2015_signed (CamelMimePart *mime_part) return TRUE; } + +/** + * camel_pgp_mime_is_rfc2015_encrypted: + * @mime_part: MIME part + * + * Checks that this part is a multipart/encrypted part following the + * rfc2015 and/or rfc3156 PGP/MIME specifications. + * + * Returns %TRUE if this looks to be a valid PGP/MIME + * multipart/encrypted part or %FALSE otherwise. + **/ gboolean camel_pgp_mime_is_rfc2015_encrypted (CamelMimePart *mime_part) { @@ -115,7 +122,7 @@ camel_pgp_mime_is_rfc2015_encrypted (CamelMimePart *mime_part) type = camel_mime_part_get_content_type (mime_part); if (!header_content_type_is (type, "multipart", "encrypted")) return FALSE; - + #ifdef ENABLE_PEDANTIC_PGPMIME /* check that we have a protocol param with the value: "application/pgp-encrypted" */ param = header_content_type_param (type, "protocol"); @@ -145,464 +152,3 @@ camel_pgp_mime_is_rfc2015_encrypted (CamelMimePart *mime_part) return TRUE; } - - -static void -pgp_mime_part_sign_restore_part (CamelMimePart *mime_part, GSList **encodings) -{ - CamelDataWrapper *wrapper; - - wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part)); - if (!wrapper) - return; - - if (CAMEL_IS_MULTIPART (wrapper)) { - int parts, i; - - parts = camel_multipart_get_number (CAMEL_MULTIPART (wrapper)); - for (i = 0; i < parts; i++) { - CamelMimePart *part = camel_multipart_get_part (CAMEL_MULTIPART (wrapper), i); - - pgp_mime_part_sign_restore_part (part, encodings); - } - } else { - CamelMimePartEncodingType encoding; - - if (CAMEL_IS_MIME_MESSAGE (wrapper)) { - /* restore the message parts' subparts */ - pgp_mime_part_sign_restore_part (CAMEL_MIME_PART (wrapper), encodings); - } else { - encoding = GPOINTER_TO_INT ((*encodings)->data); - - camel_mime_part_set_encoding (mime_part, encoding); - - *encodings = (*encodings)->next; - } - } -} - -static void -pgp_mime_part_sign_prepare_part (CamelMimePart *mime_part, GSList **encodings) -{ - CamelDataWrapper *wrapper; - int parts, i; - - wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part)); - if (!wrapper) - return; - - if (CAMEL_IS_MULTIPART (wrapper)) { - parts = camel_multipart_get_number (CAMEL_MULTIPART (wrapper)); - for (i = 0; i < parts; i++) { - CamelMimePart *part = camel_multipart_get_part (CAMEL_MULTIPART (wrapper), i); - - pgp_mime_part_sign_prepare_part (part, encodings); - } - } else { - CamelMimePartEncodingType encoding, best; - CamelStream *stream, *filtered_stream; - CamelMimeFilterBestenc *bestenc; - guint32 flags; - - if (CAMEL_IS_MIME_MESSAGE (wrapper)) { - /* prepare the message parts' subparts */ - pgp_mime_part_sign_prepare_part (CAMEL_MIME_PART (wrapper), encodings); - } else { - encoding = camel_mime_part_get_encoding (mime_part); - - if (encoding != CAMEL_MIME_PART_ENCODING_BASE64) { - flags = CAMEL_BESTENC_GET_ENCODING; - - stream = camel_stream_null_new (); - filtered_stream = (CamelStream *) camel_stream_filter_new_with_stream (stream); - camel_object_unref (CAMEL_OBJECT (stream)); - bestenc = camel_mime_filter_bestenc_new (flags); - camel_stream_filter_add (CAMEL_STREAM_FILTER (filtered_stream), - CAMEL_MIME_FILTER (bestenc)); - - camel_data_wrapper_write_to_stream (wrapper, filtered_stream); - - best = camel_mime_filter_bestenc_get_best_encoding (bestenc, CAMEL_BESTENC_7BIT); - - camel_object_unref (CAMEL_OBJECT (filtered_stream)); - camel_object_unref (CAMEL_OBJECT (bestenc)); - - if (encoding != best) { - camel_mime_part_set_encoding (mime_part, best); - - *encodings = g_slist_append (*encodings, GINT_TO_POINTER (encoding)); - } - } - } - } -} - - -/** - * camel_pgp_mime_part_sign: - * @cipher: PGP Cipher Context - * @mime_part: a MIME part that will be replaced by a pgp signed part - * @userid: userid to sign with - * @hash: one of CAMEL_PGP_HASH_TYPE_MD5 or CAMEL_PGP_HASH_TYPE_SHA1 - * @ex: exception which will be set if there are any errors. - * - * Constructs a PGP/MIME multipart in compliance with rfc2015 and - * replaces @part with the generated multipart/signed. On failure, - * @ex will be set and #part will remain untouched. - **/ -void -camel_pgp_mime_part_sign (CamelCipherContext *cipher, CamelMimePart **mime_part, const char *userid, - CamelCipherHash hash, CamelException *ex) -{ - CamelMimePart *part, *signed_part; - CamelMultipart *multipart; - CamelContentType *mime_type; - CamelStreamFilter *filtered_stream; - CamelMimeFilter *crlf_filter, *from_filter, *chomp_filter; - CamelStream *stream, *sigstream; - GSList *encodings = NULL; - char *hash_type = NULL; - - g_return_if_fail (*mime_part != NULL); - g_return_if_fail (CAMEL_IS_MIME_PART (*mime_part)); - g_return_if_fail (userid != NULL); - - part = *mime_part; - - /* Prepare all the parts for signing... */ - pgp_mime_part_sign_prepare_part (part, &encodings); - - /* get the cleartext */ - stream = camel_stream_mem_new (); - filtered_stream = camel_stream_filter_new_with_stream (stream); - - /* Note: see rfc3156, section 3 - second note */ - from_filter = CAMEL_MIME_FILTER (camel_mime_filter_from_new ()); - camel_stream_filter_add (filtered_stream, CAMEL_MIME_FILTER (from_filter)); - camel_object_unref (CAMEL_OBJECT (from_filter)); - - /* Note: see rfc3156, section 5.4 (this is the big thing that changed between rfc2015 and rfc3156) */ - chomp_filter = camel_mime_filter_chomp_new (); - camel_stream_filter_add (filtered_stream, CAMEL_MIME_FILTER (chomp_filter)); - camel_object_unref (CAMEL_OBJECT (chomp_filter)); - - /* Note: see rfc2015 or rfc3156, section 5.1 */ - crlf_filter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_ENCODE, - CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY); - camel_stream_filter_add (filtered_stream, CAMEL_MIME_FILTER (crlf_filter)); - camel_object_unref (CAMEL_OBJECT (crlf_filter)); - - camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (part), CAMEL_STREAM (filtered_stream)); - camel_stream_flush (CAMEL_STREAM (filtered_stream)); - camel_object_unref (CAMEL_OBJECT (filtered_stream)); - - /* reset the stream */ - camel_stream_reset (stream); - - d(printf ("attempting to sign data:\n----- BEGIN SIGNED PART -----\n%.*s----- END SIGNED PART -----\n", - CAMEL_STREAM_MEM (stream)->buffer->len, CAMEL_STREAM_MEM (stream)->buffer->data)); - - /* construct the signature stream */ - sigstream = camel_stream_mem_new (); - - switch (hash) { - case CAMEL_CIPHER_HASH_MD2: - /* this is a new addition with rfc3156 */ - hash_type = "pgp-md2"; - break; - case CAMEL_CIPHER_HASH_MD5: - hash_type = "pgp-md5"; - break; - case CAMEL_CIPHER_HASH_SHA1: - hash_type = "pgp-sha1"; - break; - case CAMEL_CIPHER_HASH_RIPEMD160: - hash_type = "pgp-ripemd160"; - break; - default: - /* set a reasonable default */ - hash = CAMEL_CIPHER_HASH_SHA1; - hash_type = "pgp-sha1"; - break; - } - - /* get the signature */ - if (camel_cipher_sign (cipher, userid, hash, stream, sigstream, ex) == -1) { - GSList *list; - - camel_object_unref (CAMEL_OBJECT (stream)); - camel_object_unref (CAMEL_OBJECT (sigstream)); - - /* restore the original encoding */ - list = encodings; - pgp_mime_part_sign_restore_part (part, &list); - g_slist_free (encodings); - return; - } - - camel_object_unref (CAMEL_OBJECT (stream)); - camel_stream_reset (sigstream); - - /* we don't need these anymore... */ - g_slist_free (encodings); - - /* construct the pgp-signature mime part */ - signed_part = camel_mime_part_new (); - camel_mime_part_set_content (signed_part, CAMEL_STREAM_MEM (sigstream)->buffer->data, - CAMEL_STREAM_MEM (sigstream)->buffer->len, - "application/pgp-signature; name=signature.asc"); - camel_mime_part_set_description (signed_part, _("This is a digitally signed message part")); - camel_object_unref (CAMEL_OBJECT (sigstream)); - - /* construct the container multipart/signed */ - multipart = camel_multipart_new (); - - mime_type = header_content_type_new ("multipart", "signed"); - header_content_type_set_param (mime_type, "micalg", hash_type); - header_content_type_set_param (mime_type, "protocol", "application/pgp-signature"); - camel_data_wrapper_set_mime_type_field (CAMEL_DATA_WRAPPER (multipart), mime_type); - header_content_type_unref (mime_type); - - camel_multipart_set_boundary (multipart, NULL); - - /* add the parts to the multipart */ - camel_multipart_add_part (multipart, part); - camel_object_unref (CAMEL_OBJECT (part)); - camel_multipart_add_part (multipart, signed_part); - camel_object_unref (CAMEL_OBJECT (signed_part)); - - /* replace the input part with the output part */ - *mime_part = camel_mime_part_new (); - camel_medium_set_content_object (CAMEL_MEDIUM (*mime_part), - CAMEL_DATA_WRAPPER (multipart)); - camel_object_unref (CAMEL_OBJECT (multipart)); -} - - -/** - * camel_pgp_mime_part_verify: - * @cipher: PGP Cipher Context - * @mime_part: a multipart/signed MIME Part - * @ex: exception - * - * Returns a CamelCipherValidity on success or NULL on fail. - **/ -CamelCipherValidity * -camel_pgp_mime_part_verify (CamelCipherContext *cipher, CamelMimePart *mime_part, CamelException *ex) -{ - CamelDataWrapper *wrapper; - CamelMultipart *multipart; - CamelMimePart *part, *sigpart; - CamelStreamFilter *filtered_stream; - CamelMimeFilter *crlf_filter, *chomp_filter; - CamelStream *stream, *sigstream; - CamelCipherValidity *valid; - - g_return_val_if_fail (mime_part != NULL, NULL); - g_return_val_if_fail (CAMEL_IS_MIME_PART (mime_part), NULL); - - if (!camel_pgp_mime_is_rfc2015_signed (mime_part)) - return NULL; - - wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part)); - multipart = CAMEL_MULTIPART (wrapper); - - /* get the plain part */ - part = camel_multipart_get_part (multipart, 0); - stream = camel_stream_mem_new (); - filtered_stream = camel_stream_filter_new_with_stream (stream); - - /* Note: see rfc3156, section 5.4 (this is the big thing that changed between rfc2015 and rfc3156) */ - chomp_filter = camel_mime_filter_chomp_new (); - camel_stream_filter_add (filtered_stream, CAMEL_MIME_FILTER (chomp_filter)); - camel_object_unref (CAMEL_OBJECT (chomp_filter)); - - /* Note: see rfc2015 or rfc3156, section 5.1 */ - crlf_filter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_ENCODE, - CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY); - camel_stream_filter_add (filtered_stream, CAMEL_MIME_FILTER (crlf_filter)); - camel_object_unref (CAMEL_OBJECT (crlf_filter)); - - wrapper = CAMEL_DATA_WRAPPER (part); - camel_data_wrapper_write_to_stream (wrapper, CAMEL_STREAM (filtered_stream)); - camel_stream_flush (CAMEL_STREAM (filtered_stream)); - camel_object_unref (CAMEL_OBJECT (filtered_stream)); - camel_stream_reset (stream); - - /* get the signed part */ - sigpart = camel_multipart_get_part (multipart, 1); - sigstream = camel_stream_mem_new (); - camel_data_wrapper_write_to_stream (camel_medium_get_content_object (CAMEL_MEDIUM (sigpart)), - sigstream); - camel_stream_reset (sigstream); - - /* verify */ - valid = camel_cipher_verify (cipher, CAMEL_CIPHER_HASH_DEFAULT, stream, sigstream, ex); - - d(printf ("attempted to verify data:\n----- BEGIN SIGNED PART -----\n%.*s----- END SIGNED PART -----\n", - CAMEL_STREAM_MEM (stream)->buffer->len, CAMEL_STREAM_MEM (stream)->buffer->data)); - - camel_object_unref (CAMEL_OBJECT (sigstream)); - camel_object_unref (CAMEL_OBJECT (stream)); - - return valid; -} - - -/** - * camel_pgp_mime_part_encrypt: - * @cipher: PGP Cipher Context - * @mime_part: a MIME part that will be replaced by a pgp encrypted part - * @recipients: list of recipient PGP Key IDs - * @ex: exception which will be set if there are any errors. - * - * Constructs a PGP/MIME multipart in compliance with rfc2015 and - * replaces #mime_part with the generated multipart/signed. On failure, - * #ex will be set and #part will remain untouched. - **/ -void -camel_pgp_mime_part_encrypt (CamelCipherContext *cipher, CamelMimePart **mime_part, - GPtrArray *recipients, CamelException *ex) -{ - CamelMultipart *multipart; - CamelMimePart *part, *version_part, *encrypted_part; - CamelContentType *mime_type; - CamelStreamFilter *filtered_stream; - CamelMimeFilter *crlf_filter; - CamelStream *stream, *ciphertext; - - g_return_if_fail (*mime_part != NULL); - g_return_if_fail (CAMEL_IS_MIME_PART (*mime_part)); - g_return_if_fail (recipients != NULL); - - part = *mime_part; - - /* get the contents */ - stream = camel_stream_mem_new (); - crlf_filter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_ENCODE, - CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY); - filtered_stream = camel_stream_filter_new_with_stream (stream); - camel_stream_filter_add (filtered_stream, CAMEL_MIME_FILTER (crlf_filter)); - camel_object_unref (CAMEL_OBJECT (crlf_filter)); - camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (part), CAMEL_STREAM (filtered_stream)); - camel_stream_flush (CAMEL_STREAM (filtered_stream)); - camel_object_unref (CAMEL_OBJECT (filtered_stream)); - camel_stream_reset (stream); - - /* pgp encrypt */ - ciphertext = camel_stream_mem_new (); - if (camel_cipher_encrypt (cipher, FALSE, NULL, recipients, stream, ciphertext, ex) == -1) { - camel_object_unref (CAMEL_OBJECT (stream)); - camel_object_unref (CAMEL_OBJECT (ciphertext)); - return; - } - - camel_object_unref (CAMEL_OBJECT (stream)); - camel_stream_reset (ciphertext); - - /* construct the version part */ - version_part = camel_mime_part_new (); - camel_mime_part_set_encoding (version_part, CAMEL_MIME_PART_ENCODING_7BIT); - camel_mime_part_set_content (version_part, "Version: 1", strlen ("Version: 1"), - "application/pgp-encrypted"); - - /* construct the pgp-encrypted mime part */ - encrypted_part = camel_mime_part_new (); - camel_mime_part_set_content (encrypted_part, CAMEL_STREAM_MEM (ciphertext)->buffer->data, - CAMEL_STREAM_MEM (ciphertext)->buffer->len, - "application/octet-stream; name=encrypted.asc"); - camel_object_unref (CAMEL_OBJECT (ciphertext)); - camel_mime_part_set_encoding (encrypted_part, CAMEL_MIME_PART_ENCODING_7BIT); - - /* construct the container multipart/encrypted */ - multipart = camel_multipart_new (); - - mime_type = header_content_type_new ("multipart", "encrypted"); - header_content_type_set_param (mime_type, "protocol", "application/pgp-encrypted"); - camel_data_wrapper_set_mime_type_field (CAMEL_DATA_WRAPPER (multipart), mime_type); - header_content_type_unref (mime_type); - - camel_multipart_set_boundary (multipart, NULL); - - /* add the parts to the multipart */ - camel_multipart_add_part (multipart, version_part); - camel_object_unref (CAMEL_OBJECT (version_part)); - camel_multipart_add_part (multipart, encrypted_part); - camel_object_unref (CAMEL_OBJECT (encrypted_part)); - - /* replace the input part with the output part */ - camel_object_unref (CAMEL_OBJECT (*mime_part)); - *mime_part = camel_mime_part_new (); - camel_medium_set_content_object (CAMEL_MEDIUM (*mime_part), - CAMEL_DATA_WRAPPER (multipart)); - camel_object_unref (CAMEL_OBJECT (multipart)); -} - - -/** - * camel_pgp_mime_part_decrypt: - * @cipher: PGP Cipher Context - * @mime_part: a multipart/encrypted MIME Part - * @ex: exception - * - * Returns the decrypted MIME Part on success or NULL on fail. - **/ -CamelMimePart * -camel_pgp_mime_part_decrypt (CamelCipherContext *cipher, CamelMimePart *mime_part, CamelException *ex) -{ - CamelDataWrapper *wrapper; - CamelMultipart *multipart; - CamelMimePart *encrypted_part, *part; - CamelContentType *mime_type; - CamelStream *stream, *ciphertext; - CamelStreamFilter *filtered_stream; - CamelMimeFilter *crlf_filter; - - g_return_val_if_fail (mime_part != NULL, NULL); - g_return_val_if_fail (CAMEL_IS_MIME_PART (mime_part), NULL); - - /* make sure the mime part is a multipart/encrypted */ - if (!camel_pgp_mime_is_rfc2015_encrypted (mime_part)) - return NULL; - - wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (mime_part)); - multipart = CAMEL_MULTIPART (wrapper); - - /* get the encrypted part (second part) */ - encrypted_part = camel_multipart_get_part (multipart, 1 /* second part starting at 0 */); - mime_type = camel_mime_part_get_content_type (encrypted_part); - if (!header_content_type_is (mime_type, "application", "octet-stream")) - return NULL; - - /* get the ciphertext */ - ciphertext = camel_stream_mem_new (); - camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (encrypted_part), ciphertext); - camel_stream_reset (ciphertext); - - /* get the cleartext */ - stream = camel_stream_mem_new (); - if (camel_cipher_decrypt (cipher, ciphertext, stream, ex) == -1) { - camel_object_unref (CAMEL_OBJECT (ciphertext)); - camel_object_unref (CAMEL_OBJECT (stream)); - return NULL; - } - - camel_object_unref (CAMEL_OBJECT (ciphertext)); - camel_stream_reset (stream); - - /* construct the new decrypted mime part from the stream */ - part = camel_mime_part_new (); - - crlf_filter = camel_mime_filter_crlf_new (CAMEL_MIME_FILTER_CRLF_DECODE, - CAMEL_MIME_FILTER_CRLF_MODE_CRLF_ONLY); - filtered_stream = camel_stream_filter_new_with_stream (stream); - camel_object_unref (CAMEL_OBJECT (stream)); - camel_stream_filter_add (filtered_stream, CAMEL_MIME_FILTER (crlf_filter)); - camel_object_unref (CAMEL_OBJECT (crlf_filter)); - - camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (part), CAMEL_STREAM (filtered_stream)); - - camel_object_unref (CAMEL_OBJECT (filtered_stream)); - - return part; -} diff --git a/camel/camel-pgp-mime.h b/camel/camel-pgp-mime.h index e5dec18cce..61d1478928 100644 --- a/camel/camel-pgp-mime.h +++ b/camel/camel-pgp-mime.h @@ -21,13 +21,12 @@ */ -#ifndef CAMEL_PGP_MIME_H -#define CAMEL_PGP_MIME_H +#ifndef __CAMEL_PGP_MIME_H__ +#define __CAMEL_PGP_MIME_H__ #include <glib.h> #include <camel/camel-multipart.h> #include <camel/camel-mime-part.h> -#include <camel/camel-pgp-context.h> #include <camel/camel-exception.h> #ifdef __cplusplus @@ -38,27 +37,8 @@ extern "C" { gboolean camel_pgp_mime_is_rfc2015_signed (CamelMimePart *part); gboolean camel_pgp_mime_is_rfc2015_encrypted (CamelMimePart *part); -void camel_pgp_mime_part_sign (CamelCipherContext *cipher, - CamelMimePart **mime_part, - const char *userid, - CamelCipherHash hash, - CamelException *ex); - -CamelCipherValidity *camel_pgp_mime_part_verify (CamelCipherContext *cipher, - CamelMimePart *mime_part, - CamelException *ex); - -void camel_pgp_mime_part_encrypt (CamelCipherContext *cipher, - CamelMimePart **mime_part, - GPtrArray *recipients, - CamelException *ex); - -CamelMimePart *camel_pgp_mime_part_decrypt (CamelCipherContext *cipher, - CamelMimePart *mime_part, - CamelException *ex); - #ifdef __cplusplus } #endif /* __cplusplus */ -#endif /* ! CAMEL_PGP_MIME_H */ +#endif /* __CAMEL_PGP_MIME_H__ */ diff --git a/camel/camel.h b/camel/camel.h index 0ad03e28a3..c5f158e42d 100644 --- a/camel/camel.h +++ b/camel/camel.h @@ -60,7 +60,6 @@ extern "C" { #include <camel/camel-multipart.h> #include <camel/camel-multipart-encrypted.h> #include <camel/camel-multipart-signed.h> -#include <camel/camel-pgp-context.h> #include <camel/camel-gpg-context.h> #include <camel/camel-pgp-mime.h> #include <camel/camel-provider.h> |