Fix CID 1491093: attrib leaked if attvalue is null
[claws.git] / src / privacy.c
blobfc4e60c07df94376a1e7f1f7465e6d9eaa9e04c0
1 /*
2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2021 the Claws Mail team and Hiroyuki Yamamoto
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "config.h"
22 #include <glib.h>
23 #include <glib/gi18n.h>
25 #include "privacy.h"
26 #include "procmime.h"
27 #include "procmsg.h"
29 static GSList *systems = NULL;
30 static gchar *privacy_last_error = NULL;
32 void privacy_set_error(const gchar *format, ...)
34 va_list args;
35 gchar buf[BUFSIZ];
37 va_start(args, format);
38 g_vsnprintf(buf, BUFSIZ, format, args);
39 va_end(args);
40 g_free(privacy_last_error);
41 privacy_last_error = g_strdup(buf);
44 static gchar tmp_privacy_error[BUFSIZ];
46 void privacy_reset_error(void)
48 g_free(privacy_last_error);
49 privacy_last_error = NULL;
52 gboolean privacy_peek_error(void)
54 return (privacy_last_error != NULL);
57 const gchar *privacy_get_error (void)
59 if (privacy_last_error) {
60 strncpy2(tmp_privacy_error, privacy_last_error, BUFSIZ-1);
61 privacy_reset_error();
62 return tmp_privacy_error;
63 } else {
64 return _("Unknown error");
68 static PrivacySystem *privacy_data_get_system(PrivacyData *data)
70 /* Make sure the cached system is still registered */
71 if (data->system && g_slist_find(systems, data->system))
72 return data->system;
73 else
74 return NULL;
76 /**
77 * Register a new Privacy System
79 * \param system The Privacy System that should be registered
81 void privacy_register_system(PrivacySystem *system)
83 systems = g_slist_append(systems, system);
86 /**
87 * Unregister a new Privacy System. The system must not be in
88 * use anymore when it is unregistered.
90 * \param system The Privacy System that should be unregistered
92 void privacy_unregister_system(PrivacySystem *system)
94 systems = g_slist_remove(systems, system);
97 /**
98 * Free a PrivacyData of a PrivacySystem
100 * \param privacydata The data to free
102 void privacy_free_privacydata(PrivacyData *privacydata)
104 PrivacySystem *system = NULL;
106 cm_return_if_fail(privacydata != NULL);
108 system = privacy_data_get_system(privacydata);
109 if (!system)
110 return;
111 system->free_privacydata(privacydata);
114 void privacy_free_signature_data(SignatureData *sig_data)
116 cm_return_if_fail(sig_data != NULL);
118 g_free(sig_data->info_short);
119 g_free(sig_data->info_full);
120 g_free(sig_data);
123 void privacy_free_sig_check_task_result(gpointer data)
125 SigCheckTaskResult *result = (SigCheckTaskResult *)data;
127 privacy_free_signature_data(result->sig_data);
128 if (result->newinfo)
129 procmime_mimeinfo_free_all(&result->newinfo);
130 g_free(result);
134 * Check if a MimeInfo is signed with one of the available
135 * privacy system. If a privacydata is set in the MimeInfo
136 * it will directory return the return value by the system
137 * set in the privacy data or check all available privacy
138 * systems otherwise.
140 * \return True if the MimeInfo has a signature
142 gboolean privacy_mimeinfo_is_signed(MimeInfo *mimeinfo)
144 GSList *cur;
145 cm_return_val_if_fail(mimeinfo != NULL, FALSE);
147 if (mimeinfo->privacy != NULL) {
148 PrivacySystem *system =
149 privacy_data_get_system(mimeinfo->privacy);
151 if (system == NULL) {
152 mimeinfo->privacy = NULL;
153 goto try_others;
156 if (system->is_signed != NULL)
157 return system->is_signed(mimeinfo);
158 else
159 return FALSE;
161 try_others:
162 for(cur = systems; cur != NULL; cur = g_slist_next(cur)) {
163 PrivacySystem *system = (PrivacySystem *) cur->data;
165 if(system->is_signed != NULL && system->is_signed(mimeinfo))
166 return TRUE;
169 return FALSE;
172 struct SignedState {
173 MsgInfo *msginfo;
174 gchar **system;
177 static void msginfo_set_signed_flag(GNode *node, gpointer data)
179 struct SignedState *sstate = (struct SignedState *)data;
180 MsgInfo *msginfo = sstate->msginfo;
181 MimeInfo *mimeinfo = node->data;
183 if (privacy_mimeinfo_is_signed(mimeinfo)) {
184 procmsg_msginfo_set_flags(msginfo, 0, MSG_SIGNED);
185 if (sstate->system && !*(sstate->system) && mimeinfo->privacy)
186 *(sstate->system) = g_strdup(mimeinfo->privacy->system->id);
188 if (privacy_mimeinfo_is_encrypted(mimeinfo)) {
189 procmsg_msginfo_set_flags(msginfo, 0, MSG_ENCRYPTED);
190 if (sstate->system && !*(sstate->system) && mimeinfo->privacy)
191 *(sstate->system) = g_strdup(mimeinfo->privacy->system->id);
192 } else {
193 /* searching inside encrypted parts doesn't really make sense */
194 g_node_children_foreach(mimeinfo->node, G_TRAVERSE_ALL, msginfo_set_signed_flag, sstate);
198 void privacy_msginfo_get_signed_state(MsgInfo *msginfo, gchar **system)
200 struct SignedState sstate;
201 MimeInfo *mimeinfo = procmime_scan_message(msginfo);
202 if (!mimeinfo)
203 return;
204 sstate.msginfo = msginfo;
205 sstate.system = system;
206 g_node_children_foreach(mimeinfo->node, G_TRAVERSE_ALL, msginfo_set_signed_flag, &sstate);
210 * Check the signature of a MimeInfo. privacy_mimeinfo_is_signed
211 * should be called before otherwise it is done by this function.
212 * If the MimeInfo is not signed an error code will be returned.
214 * \return Error code indicating the result of the check,
215 * < 0 if an error occurred
217 gint privacy_mimeinfo_check_signature(MimeInfo *mimeinfo,
218 GCancellable *cancellable,
219 GAsyncReadyCallback callback,
220 gpointer user_data)
222 PrivacySystem *system;
224 if (mimeinfo == NULL)
225 g_error("siginfo was NULL");
227 if (mimeinfo->privacy == NULL) {
228 g_warning("mimeinfo->privacy was NULL");
230 privacy_mimeinfo_is_signed(mimeinfo);
231 if (mimeinfo->privacy == NULL) {
232 g_error("failed to set up PrivacyData");
236 system = privacy_data_get_system(mimeinfo->privacy);
237 if (system == NULL)
238 g_error("failed to get privacy system");
239 else if (system->check_signature == NULL)
240 g_error("didn't find check_signature function");
242 return system->check_signature(mimeinfo, cancellable, callback, user_data);
245 SignatureStatus privacy_mimeinfo_get_sig_status(MimeInfo *mimeinfo)
247 PrivacySystem *system;
249 cm_return_val_if_fail(mimeinfo != NULL, -1);
251 if (mimeinfo->privacy == NULL) {
252 privacy_mimeinfo_is_signed(mimeinfo);
254 if (mimeinfo->privacy == NULL)
255 return SIGNATURE_UNCHECKED;
258 system = privacy_data_get_system(mimeinfo->privacy);
259 if (system == NULL)
260 return SIGNATURE_UNCHECKED;
262 if (mimeinfo->sig_data == NULL)
263 return SIGNATURE_UNCHECKED;
264 else
265 return mimeinfo->sig_data->status;
268 gchar *privacy_mimeinfo_get_sig_info(MimeInfo *mimeinfo, gboolean full)
270 PrivacySystem *system;
271 gchar *info;
273 cm_return_val_if_fail(mimeinfo != NULL, NULL);
275 if (mimeinfo->privacy == NULL) {
276 privacy_mimeinfo_is_signed(mimeinfo);
278 if (mimeinfo->privacy == NULL)
279 return _("No signature found");
282 system = privacy_data_get_system(mimeinfo->privacy);
283 if (system == NULL)
284 return _("No signature found");
286 if (mimeinfo->sig_data == NULL)
287 return _("No information available");
289 info = full ? mimeinfo->sig_data->info_full : mimeinfo->sig_data->info_short;
290 if (info == NULL)
291 return _("No information available");
293 return info;
296 gboolean privacy_mimeinfo_is_encrypted(MimeInfo *mimeinfo)
298 GSList *cur;
299 cm_return_val_if_fail(mimeinfo != NULL, FALSE);
301 for(cur = systems; cur != NULL; cur = g_slist_next(cur)) {
302 PrivacySystem *system = (PrivacySystem *) cur->data;
304 if(system->is_encrypted != NULL && system->is_encrypted(mimeinfo))
305 return TRUE;
308 return FALSE;
311 static gint decrypt(MimeInfo *mimeinfo, PrivacySystem *system)
313 MimeInfo *decryptedinfo, *parentinfo;
314 gint childnumber;
316 cm_return_val_if_fail(system->decrypt != NULL, -1);
318 decryptedinfo = system->decrypt(mimeinfo);
319 if (decryptedinfo == NULL)
320 return -1;
322 parentinfo = procmime_mimeinfo_parent(mimeinfo);
323 childnumber = g_node_child_index(parentinfo->node, mimeinfo);
325 procmime_mimeinfo_free_all(&mimeinfo);
327 g_node_insert(parentinfo->node, childnumber, decryptedinfo->node);
329 return 0;
332 gint privacy_mimeinfo_decrypt(MimeInfo *mimeinfo)
334 GSList *cur;
335 cm_return_val_if_fail(mimeinfo != NULL, FALSE);
337 procmime_decode_content(mimeinfo);
339 for(cur = systems; cur != NULL; cur = g_slist_next(cur)) {
340 PrivacySystem *system = (PrivacySystem *) cur->data;
342 if(system->is_encrypted != NULL && system->is_encrypted(mimeinfo))
343 return decrypt(mimeinfo, system);
346 return -1;
349 GSList *privacy_get_system_ids()
351 GSList *cur;
352 GSList *ret = NULL;
354 for(cur = systems; cur != NULL; cur = g_slist_next(cur)) {
355 PrivacySystem *system = (PrivacySystem *) cur->data;
357 ret = g_slist_append(ret, g_strdup(system->id));
360 return ret;
363 static PrivacySystem *privacy_get_system(const gchar *id)
365 GSList *cur;
367 cm_return_val_if_fail(id != NULL, NULL);
369 for(cur = systems; cur != NULL; cur = g_slist_next(cur)) {
370 PrivacySystem *system = (PrivacySystem *) cur->data;
372 if(strcmp(id, system->id) == 0)
373 return system;
376 return NULL;
379 const gchar *privacy_system_get_name(const gchar *id)
381 PrivacySystem *system;
383 cm_return_val_if_fail(id != NULL, NULL);
385 system = privacy_get_system(id);
386 if (system == NULL)
387 return NULL;
389 return system->name;
392 gboolean privacy_system_can_sign(const gchar *id)
394 PrivacySystem *system;
396 cm_return_val_if_fail(id != NULL, FALSE);
398 system = privacy_get_system(id);
399 if (system == NULL)
400 return FALSE;
402 return system->can_sign;
405 gboolean privacy_system_can_encrypt(const gchar *id)
407 PrivacySystem *system;
409 cm_return_val_if_fail(id != NULL, FALSE);
411 system = privacy_get_system(id);
412 if (system == NULL)
413 return FALSE;
415 return system->can_encrypt;
418 gboolean privacy_sign(const gchar *id, MimeInfo *target, PrefsAccount *account, const gchar *from_addr)
420 PrivacySystem *system;
422 cm_return_val_if_fail(id != NULL, FALSE);
423 cm_return_val_if_fail(target != NULL, FALSE);
425 system = privacy_get_system(id);
426 if (system == NULL)
427 return FALSE;
428 if (!system->can_sign)
429 return FALSE;
430 if (system->sign == NULL)
431 return FALSE;
433 return system->sign(target, account, from_addr);
436 gchar *privacy_get_encrypt_data(const gchar *id, GSList *recp_names)
438 PrivacySystem *system;
439 gchar *ret = NULL;
440 GSList *uniq_names = NULL, *cur;
442 cm_return_val_if_fail(id != NULL, NULL);
443 cm_return_val_if_fail(recp_names != NULL, NULL);
445 system = privacy_get_system(id);
446 if (system == NULL)
447 return NULL;
448 if (!system->can_encrypt)
449 return NULL;
450 if (system->get_encrypt_data == NULL)
451 return NULL;
453 for (cur = recp_names; cur; cur = cur->next) {
454 if (!g_slist_find_custom(uniq_names, cur->data, (GCompareFunc)strcmp)) {
455 uniq_names = g_slist_prepend(uniq_names, cur->data);
458 ret = system->get_encrypt_data(uniq_names);
460 g_slist_free(uniq_names);
461 return ret;
464 const gchar *privacy_get_encrypt_warning(const gchar *id)
466 PrivacySystem *system;
468 cm_return_val_if_fail(id != NULL, NULL);
470 system = privacy_get_system(id);
471 if (system == NULL)
472 return NULL;
473 if (!system->can_encrypt)
474 return NULL;
475 if (system->get_encrypt_warning == NULL)
476 return NULL;
478 return system->get_encrypt_warning();
481 void privacy_inhibit_encrypt_warning(const gchar *id, gboolean inhibit)
483 PrivacySystem *system;
485 cm_return_if_fail(id != NULL);
487 system = privacy_get_system(id);
488 if (system == NULL)
489 return;
490 if (!system->can_encrypt)
491 return;
492 if (system->inhibit_encrypt_warning == NULL)
493 return;
495 system->inhibit_encrypt_warning(inhibit);
498 gboolean privacy_encrypt(const gchar *id, MimeInfo *mimeinfo, const gchar *encdata)
500 PrivacySystem *system;
502 cm_return_val_if_fail(id != NULL, FALSE);
503 cm_return_val_if_fail(mimeinfo != NULL, FALSE);
504 if (encdata == NULL) {
505 privacy_set_error(_("No recipient keys defined."));
506 return FALSE;
509 system = privacy_get_system(id);
510 if (system == NULL)
511 return FALSE;
512 if (!system->can_encrypt)
513 return FALSE;
514 if (system->encrypt == NULL)
515 return FALSE;
517 return system->encrypt(mimeinfo, encdata);
520 gboolean privacy_auto_check_signatures(MimeInfo *mimeinfo)
522 PrivacySystem *system;
524 cm_return_val_if_fail(mimeinfo != NULL, FALSE);
526 if (mimeinfo->privacy == NULL)
527 privacy_mimeinfo_is_signed(mimeinfo);
529 if (mimeinfo->privacy == NULL)
530 return FALSE;
532 system = privacy_data_get_system(mimeinfo->privacy);
533 if (system == NULL)
534 return FALSE;
535 if (system->auto_check_signatures == NULL)
536 return FALSE;
538 return system->auto_check_signatures();