talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

commit 1de8172c2e3c8eef2bac4a2cd9ebe727c0773f8a
parent 306bf2ef35f2d074d786a85bcf5454cfc5f4b2e1
Author: Paul <paul@claws-mail.org>
Date:   Thu, 11 Jul 2013 15:17:48 +0100

fix bug 2961, 'Partial retrieval not available with PGP/Inline encrypted messages'

do a more thorough check before deciding to go ahead with a (ultimately
failed) decryption attempt: check for the end of the encrypted block,
don't just assume, (never assume, it makes an ...), that it must be
there if the beginning of the block is found.

Move some stuff, which is now used in both -mime and -inline,  into a
new file, pgpcore/pgp_utils.[ch]

Diffstat:
Msrc/plugins/pgpcore/Makefile.am | 2++
Asrc/plugins/pgpcore/pgp_utils.c | 136+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/plugins/pgpcore/pgp_utils.h | 34++++++++++++++++++++++++++++++++++
Msrc/plugins/pgpinline/pgpinline.c | 123++++++++-----------------------------------------------------------------------
Msrc/plugins/pgpmime/pgpmime.c | 21++++++++++++++++++++-
5 files changed, 204 insertions(+), 112 deletions(-)

diff --git a/src/plugins/pgpcore/Makefile.am b/src/plugins/pgpcore/Makefile.am @@ -53,6 +53,7 @@ pgpcore_la_SOURCES = \ prefs_gpg.c \ select-keys.c \ sgpgme.c \ + pgp_utils.c \ pgp_viewer.c pluginincludedir = $(pkgincludedir)/plugins/pgpcore @@ -61,6 +62,7 @@ plugininclude_HEADERS = \ prefs_gpg.h \ select-keys.h \ sgpgme.h \ + pgp_utils.h \ pgp_viewer.h pgpcore_la_LDFLAGS = \ diff --git a/src/plugins/pgpcore/pgp_utils.c b/src/plugins/pgpcore/pgp_utils.c @@ -0,0 +1,136 @@ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#include "claws-features.h" +#endif + +/* + * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client + * Copyright (C) 1999-2013 Colin Leroy <colin@colino.net> and + * the Claws Mail team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifdef USE_GPGME + +#include <glib.h> + +#include "pgp_utils.h" +#include "codeconv.h" + +gchar *fp_read_noconv(FILE *fp) +{ + GByteArray *array; + guchar buf[BUFSIZ]; + gint n_read; + gchar *result = NULL; + + if (!fp) + return NULL; + array = g_byte_array_new(); + + while ((n_read = fread(buf, sizeof(gchar), sizeof(buf), fp)) > 0) { + if (n_read < sizeof(buf) && ferror(fp)) + break; + g_byte_array_append(array, buf, n_read); + } + + if (ferror(fp)) { + FILE_OP_ERROR("file stream", "fread"); + g_byte_array_free(array, TRUE); + return NULL; + } + + buf[0] = '\0'; + g_byte_array_append(array, buf, 1); + result = (gchar *)array->data; + g_byte_array_free(array, FALSE); + + return result; +} + +gchar *get_part_as_string(MimeInfo *mimeinfo) +{ + gchar *textdata = NULL; + gchar *filename = NULL; + FILE *fp; + + cm_return_val_if_fail(mimeinfo != NULL, 0); + procmime_decode_content(mimeinfo); + + if (mimeinfo->content == MIMECONTENT_MEM) + textdata = g_strdup(mimeinfo->data.mem); + else { + filename = procmime_get_tmp_file_name(mimeinfo); + if (procmime_get_part(filename, mimeinfo) < 0) { + printf("error dumping file\n"); + return NULL; + } + fp = g_fopen(filename,"rb"); + if (!fp) { + printf("error reading file\n"); + return NULL; + } + textdata = fp_read_noconv(fp); + fclose(fp); + g_unlink(filename); + g_free(filename); + } + + if (!g_utf8_validate(textdata, -1, NULL)) { + gchar *tmp = NULL; + codeconv_set_strict(TRUE); + if (procmime_mimeinfo_get_parameter(mimeinfo, "charset")) { + tmp = conv_codeset_strdup(textdata, + procmime_mimeinfo_get_parameter(mimeinfo, "charset"), + CS_UTF_8); + } + if (!tmp) { + tmp = conv_codeset_strdup(textdata, + conv_get_locale_charset_str_no_utf8(), + CS_UTF_8); + } + codeconv_set_strict(FALSE); + if (!tmp) { + tmp = conv_codeset_strdup(textdata, + conv_get_locale_charset_str_no_utf8(), + CS_UTF_8); + } + if (tmp) { + g_free(textdata); + textdata = tmp; + } + } + + return textdata; +} + +gchar *pgp_locate_armor_header(gchar *textdata, const gchar *armor_header) +{ + gchar *pos; + + pos = strstr(textdata, armor_header); + /* + * It's only a valid armor header if it's at the + * beginning of the buffer or a new line. + */ + if (pos != NULL && (pos == textdata || *(pos-1) == '\n')) + { + return pos; + } + return NULL; +} +#endif /* USE_GPGME */ diff --git a/src/plugins/pgpcore/pgp_utils.h b/src/plugins/pgpcore/pgp_utils.h @@ -0,0 +1,34 @@ +/* + * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client + * Copyright (C) 1999-2013 Colin Leroy <colin@colino.net> and + * the Claws Mail team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef __PGP_UTILS_H__ +#define __PGP_UTILS_H__ + +#ifdef HAVE_CONFIG_H +#include "claws-features.h" +#endif + +#include "procmime.h" + +gchar *fp_read_noconv(FILE *fp); +gchar *get_part_as_string(MimeInfo *mimeinfo); +gchar *pgp_locate_armor_header(gchar *textdata, const gchar *armor_header); + +#endif /* __PGP_UTILS_H__ */ diff --git a/src/plugins/pgpinline/pgpinline.c b/src/plugins/pgpinline/pgpinline.c @@ -38,6 +38,7 @@ #include <plugins/pgpcore/sgpgme.h> #include <plugins/pgpcore/prefs_gpg.h> #include <plugins/pgpcore/passphrase.h> +#include <plugins/pgpcore/pgp_utils.h> #include "quoted-printable.h" #include "base64.h" #include "codeconv.h" @@ -86,109 +87,6 @@ static void pgpinline_free_privacydata(PrivacyData *_data) g_free(data); } -static gchar *fp_read_noconv(FILE *fp) -{ - GByteArray *array; - guchar buf[BUFSIZ]; - gint n_read; - gchar *result = NULL; - - if (!fp) - return NULL; - array = g_byte_array_new(); - - while ((n_read = fread(buf, sizeof(gchar), sizeof(buf), fp)) > 0) { - if (n_read < sizeof(buf) && ferror(fp)) - break; - g_byte_array_append(array, buf, n_read); - } - - if (ferror(fp)) { - FILE_OP_ERROR("file stream", "fread"); - g_byte_array_free(array, TRUE); - return NULL; - } - - buf[0] = '\0'; - g_byte_array_append(array, buf, 1); - result = (gchar *)array->data; - g_byte_array_free(array, FALSE); - - return result; -} - -static gchar *get_part_as_string(MimeInfo *mimeinfo) -{ - gchar *textdata = NULL; - gchar *filename = NULL; - FILE *fp; - - cm_return_val_if_fail(mimeinfo != NULL, 0); - procmime_decode_content(mimeinfo); - - if (mimeinfo->content == MIMECONTENT_MEM) - textdata = g_strdup(mimeinfo->data.mem); - else { - filename = procmime_get_tmp_file_name(mimeinfo); - if (procmime_get_part(filename, mimeinfo) < 0) { - printf("error dumping file\n"); - return NULL; - } - fp = g_fopen(filename,"rb"); - if (!fp) { - printf("error reading file\n"); - return NULL; - } - textdata = fp_read_noconv(fp); - fclose(fp); - g_unlink(filename); - g_free(filename); - } - - if (!g_utf8_validate(textdata, -1, NULL)) { - gchar *tmp = NULL; - codeconv_set_strict(TRUE); - if (procmime_mimeinfo_get_parameter(mimeinfo, "charset")) { - tmp = conv_codeset_strdup(textdata, - procmime_mimeinfo_get_parameter(mimeinfo, "charset"), - CS_UTF_8); - } - if (!tmp) { - tmp = conv_codeset_strdup(textdata, - conv_get_locale_charset_str_no_utf8(), - CS_UTF_8); - } - codeconv_set_strict(FALSE); - if (!tmp) { - tmp = conv_codeset_strdup(textdata, - conv_get_locale_charset_str_no_utf8(), - CS_UTF_8); - } - if (tmp) { - g_free(textdata); - textdata = tmp; - } - } - - return textdata; -} - -static gchar *pgpinline_locate_armor_header(gchar *textdata, const gchar *armor_header) -{ - gchar *pos; - - pos = strstr(textdata, armor_header); - /* - * It's only a valid armor header if it's at the - * beginning of the buffer or a new line. - */ - if (pos != NULL && (pos == textdata || *(pos-1) == '\n')) - { - return pos; - } - return NULL; -} - static gboolean pgpinline_is_signed(MimeInfo *mimeinfo) { PrivacyDataPGP *data = NULL; @@ -351,11 +249,10 @@ static gchar *pgpinline_get_sig_info_full(MimeInfo *mimeinfo) return sgpgme_sigstat_info_full(data->ctx, data->sigstatus); } - - static gboolean pgpinline_is_encrypted(MimeInfo *mimeinfo) { - const gchar *enc_indicator = "-----BEGIN PGP MESSAGE-----"; + const gchar *begin_indicator = "-----BEGIN PGP MESSAGE-----"; + const gchar *end_indicator = "-----END PGP MESSAGE-----"; gchar *textdata; cm_return_val_if_fail(mimeinfo != NULL, FALSE); @@ -375,12 +272,16 @@ static gboolean pgpinline_is_encrypted(MimeInfo *mimeinfo) g_free(mimeinfo->subtype); mimeinfo->subtype = g_strdup("plain"); } - + textdata = get_part_as_string(mimeinfo); if (!textdata) return FALSE; - - if (!pgpinline_locate_armor_header(textdata, enc_indicator)) { + + if (!pgp_locate_armor_header(textdata, begin_indicator)) { + g_free(textdata); + return FALSE; + } + if (!pgp_locate_armor_header(textdata, end_indicator)) { g_free(textdata); return FALSE; } @@ -472,7 +373,7 @@ static MimeInfo *pgpinline_decrypt(MimeInfo *mimeinfo) } /* Store any part before encrypted text */ - pos = pgpinline_locate_armor_header(textdata, begin_indicator); + pos = pgp_locate_armor_header(textdata, begin_indicator); if (pos != NULL && (pos - textdata) > 0) { if (fwrite(textdata, 1, pos - textdata, dstfp) < pos - textdata) { FILE_OP_ERROR(fname, "fwrite"); @@ -507,7 +408,7 @@ static MimeInfo *pgpinline_decrypt(MimeInfo *mimeinfo) goto FILE_ERROR; } if (pos != NULL) { - pos = pgpinline_locate_armor_header(pos, end_indicator); + pos = pgp_locate_armor_header(pos, end_indicator); if (pos != NULL && *pos != '\0') { pos += strlen(end_indicator); if (fwrite(pos, 1, strlen(pos), dstfp) < strlen(pos)) { diff --git a/src/plugins/pgpmime/pgpmime.c b/src/plugins/pgpmime/pgpmime.c @@ -40,6 +40,7 @@ #include <plugins/pgpcore/sgpgme.h> #include <plugins/pgpcore/prefs_gpg.h> #include <plugins/pgpcore/passphrase.h> +#include <plugins/pgpcore/pgp_utils.h> #include "prefs_common.h" @@ -277,7 +278,10 @@ static gboolean pgpmime_is_encrypted(MimeInfo *mimeinfo) { MimeInfo *tmpinfo; const gchar *tmpstr; - + const gchar *begin_indicator = "-----BEGIN PGP MESSAGE-----"; + const gchar *end_indicator = "-----END PGP MESSAGE-----"; + gchar *textdata; + if (mimeinfo->type != MIMETYPE_MULTIPART) return FALSE; if (g_ascii_strcasecmp(mimeinfo->subtype, "encrypted")) @@ -300,6 +304,21 @@ static gboolean pgpmime_is_encrypted(MimeInfo *mimeinfo) if (g_ascii_strcasecmp(tmpinfo->subtype, "octet-stream")) return FALSE; + textdata = get_part_as_string(tmpinfo); + if (!textdata) + return FALSE; + + if (!pgp_locate_armor_header(textdata, begin_indicator)) { + g_free(textdata); + return FALSE; + } + if (!pgp_locate_armor_header(textdata, end_indicator)) { + g_free(textdata); + return FALSE; + } + + g_free(textdata); + return TRUE; }