1 /*
2 * e-mail-parser-application-xpkcs7mime.c
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18 #include "evolution-config.h"
19
20 #include <string.h>
21 #include <glib/gi18n-lib.h>
22
23 #include <e-util/e-util.h>
24
25 #include "e-mail-formatter-utils.h"
26 #include "e-mail-parser-extension.h"
27 #include "e-mail-part-utils.h"
28
29 typedef EMailParserExtension EMailParserApplicationSMIME;
30 typedef EMailParserExtensionClass EMailParserApplicationSMIMEClass;
31
32 GType e_mail_parser_application_smime_get_type (void);
33
34 G_DEFINE_TYPE (
35 EMailParserApplicationSMIME,
36 e_mail_parser_application_smime,
37 E_TYPE_MAIL_PARSER_EXTENSION)
38
39 static const gchar *parser_mime_types[] = {
40 "application/xpkcs7mime",
41 "application/xpkcs7-mime",
42 "application/x-pkcs7-mime",
43 "application/pkcs7-mime",
44 "application/pkcs7-signature",
45 "application/xpkcs7signature",
46 "application/xpkcs7-signature",
47 "application/x-pkcs7-signature",
48 NULL
49 };
50
51 static gboolean
empe_app_smime_parse(EMailParserExtension * extension,EMailParser * parser,CamelMimePart * part,GString * part_id,GCancellable * cancellable,GQueue * out_mail_parts)52 empe_app_smime_parse (EMailParserExtension *extension,
53 EMailParser *parser,
54 CamelMimePart *part,
55 GString *part_id,
56 GCancellable *cancellable,
57 GQueue *out_mail_parts)
58 {
59 CamelCipherContext *context;
60 CamelMimePart *opart;
61 CamelCipherValidity *valid;
62 CamelContentType *ct;
63 gboolean is_guessed;
64 GError *local_error = NULL;
65
66 ct = camel_mime_part_get_content_type (part);
67
68 /* When it's a guessed type, then rather not interpret it as a signed/encrypted message */
69 is_guessed = g_strcmp0 (camel_content_type_param (ct, E_MAIL_PART_X_EVOLUTION_GUESSED), "1") == 0;
70
71 if (is_guessed ||
72 camel_content_type_is (ct, "application", "pkcs7-signature") ||
73 camel_content_type_is (ct, "application", "xpkcs7signature") ||
74 camel_content_type_is (ct, "application", "xpkcs7-signature") ||
75 camel_content_type_is (ct, "application", "x-pkcs7-signature")) {
76 gboolean add_as_attachment = is_guessed;
77
78 if (!add_as_attachment) {
79 EMailPartList *part_list;
80
81 part_list = e_mail_parser_ref_part_list_for_operation (parser, cancellable);
82 if (part_list) {
83 CamelMimePart *parent_part;
84
85 parent_part = e_mail_part_utils_find_parent_part (e_mail_part_list_get_message (part_list), part);
86 if (parent_part) {
87 ct = camel_mime_part_get_content_type (parent_part);
88 add_as_attachment = !camel_content_type_is (ct, "multipart", "signed");
89 }
90
91 g_object_unref (part_list);
92 }
93 }
94
95 if (add_as_attachment)
96 e_mail_parser_wrap_as_non_expandable_attachment (parser, part, part_id, out_mail_parts);
97
98 return TRUE;
99 }
100
101 context = camel_smime_context_new (e_mail_parser_get_session (parser));
102
103 opart = camel_mime_part_new ();
104 valid = camel_cipher_context_decrypt_sync (
105 context, part, opart,
106 cancellable, &local_error);
107
108 e_mail_part_preserve_charset_in_content_type (part, opart);
109
110 if (local_error != NULL) {
111 e_mail_parser_error (
112 parser, out_mail_parts,
113 _("Could not parse S/MIME message: %s"),
114 local_error->message);
115 g_error_free (local_error);
116
117 } else {
118 CamelContentType *ct;
119 GQueue work_queue = G_QUEUE_INIT;
120 GList *head, *link;
121 gint len = part_id->len;
122
123 g_string_append (part_id, ".encrypted-smime");
124
125 ct = camel_data_wrapper_get_mime_type_field (CAMEL_DATA_WRAPPER (opart));
126
127 if (!ct || camel_content_type_is (ct, "text", "plain")) {
128 const gchar *mime_type;
129
130 mime_type = e_mail_part_snoop_type (opart);
131
132 if (mime_type && g_ascii_strcasecmp (mime_type, "text/plain") != 0)
133 camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (opart), mime_type);
134 }
135
136 e_mail_parser_parse_part (
137 parser, opart, part_id, cancellable, &work_queue);
138
139 g_string_truncate (part_id, len);
140
141 head = g_queue_peek_head_link (&work_queue);
142
143 /* Update validity flags of all the involved subp-arts */
144 for (link = head; link != NULL; link = g_list_next (link)) {
145 EMailPart *mail_part = link->data;
146
147 e_mail_part_update_validity (
148 mail_part, valid,
149 E_MAIL_PART_VALIDITY_SMIME);
150
151 /* Do not traverse sub-messages */
152 if (g_str_has_suffix (e_mail_part_get_id (mail_part), ".rfc822"))
153 link = e_mail_formatter_find_rfc822_end_iter (link);
154 }
155
156 e_queue_transfer (&work_queue, out_mail_parts);
157
158 /* Add a widget with details about the encryption, but only
159 * when the encrypted isn't itself secured, in that case it
160 * has created the button itself. */
161 if (!e_mail_part_is_secured (opart)) {
162 EMailPart *mail_part;
163
164 g_string_append (part_id, ".encrypted-smime.button");
165
166 e_mail_parser_parse_part_as (
167 parser, part, part_id,
168 "application/vnd.evolution.secure-button",
169 cancellable, &work_queue);
170
171 mail_part = g_queue_peek_head (&work_queue);
172
173 if (mail_part != NULL)
174 e_mail_part_update_validity (
175 mail_part, valid,
176 E_MAIL_PART_VALIDITY_SMIME);
177
178 e_queue_transfer (&work_queue, out_mail_parts);
179
180 g_string_truncate (part_id, len);
181 }
182
183 camel_cipher_validity_free (valid);
184 }
185
186 g_object_unref (opart);
187 g_object_unref (context);
188
189 return TRUE;
190 }
191
192 static void
e_mail_parser_application_smime_class_init(EMailParserExtensionClass * class)193 e_mail_parser_application_smime_class_init (EMailParserExtensionClass *class)
194 {
195 class->mime_types = parser_mime_types;
196 class->priority = G_PRIORITY_LOW;
197 class->flags = E_MAIL_PARSER_EXTENSION_INLINE;
198 class->parse = empe_app_smime_parse;
199 }
200
201 static void
e_mail_parser_application_smime_init(EMailParserExtension * extension)202 e_mail_parser_application_smime_init (EMailParserExtension *extension)
203 {
204 }
205