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/>.
23 #include <glib/gi18n.h>
29 static GSList
*systems
= NULL
;
30 static gchar
*privacy_last_error
= NULL
;
32 void privacy_set_error(const gchar
*format
, ...)
37 va_start(args
, format
);
38 g_vsnprintf(buf
, BUFSIZ
, format
, 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
;
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
))
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
);
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
);
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
);
111 system
->free_privacydata(privacydata
);
114 void privacy_free_signature_data(gpointer data
)
116 SignatureData
*sig_data
= (SignatureData
*)data
;
118 cm_return_if_fail(sig_data
!= NULL
);
120 g_free(sig_data
->info_short
);
121 g_free(sig_data
->info_full
);
125 void privacy_free_sig_check_task_result(gpointer data
)
127 SigCheckTaskResult
*result
= (SigCheckTaskResult
*)data
;
129 privacy_free_signature_data(result
->sig_data
);
131 procmime_mimeinfo_free_all(&result
->newinfo
);
136 * Check if a MimeInfo is signed with one of the available
137 * privacy system. If a privacydata is set in the MimeInfo
138 * it will directory return the return value by the system
139 * set in the privacy data or check all available privacy
142 * \return True if the MimeInfo has a signature
144 gboolean
privacy_mimeinfo_is_signed(MimeInfo
*mimeinfo
)
147 cm_return_val_if_fail(mimeinfo
!= NULL
, FALSE
);
149 if (mimeinfo
->privacy
!= NULL
) {
150 PrivacySystem
*system
=
151 privacy_data_get_system(mimeinfo
->privacy
);
153 if (system
== NULL
) {
154 mimeinfo
->privacy
= NULL
;
158 if (system
->is_signed
!= NULL
)
159 return system
->is_signed(mimeinfo
);
164 for(cur
= systems
; cur
!= NULL
; cur
= g_slist_next(cur
)) {
165 PrivacySystem
*system
= (PrivacySystem
*) cur
->data
;
167 if(system
->is_signed
!= NULL
&& system
->is_signed(mimeinfo
))
179 static void msginfo_set_signed_flag(GNode
*node
, gpointer data
)
181 struct SignedState
*sstate
= (struct SignedState
*)data
;
182 MsgInfo
*msginfo
= sstate
->msginfo
;
183 MimeInfo
*mimeinfo
= node
->data
;
185 if (privacy_mimeinfo_is_signed(mimeinfo
)) {
186 procmsg_msginfo_set_flags(msginfo
, 0, MSG_SIGNED
);
187 if (sstate
->system
&& !*(sstate
->system
) && mimeinfo
->privacy
)
188 *(sstate
->system
) = g_strdup(mimeinfo
->privacy
->system
->id
);
190 if (privacy_mimeinfo_is_encrypted(mimeinfo
)) {
191 procmsg_msginfo_set_flags(msginfo
, 0, MSG_ENCRYPTED
);
192 if (sstate
->system
&& !*(sstate
->system
) && mimeinfo
->privacy
)
193 *(sstate
->system
) = g_strdup(mimeinfo
->privacy
->system
->id
);
195 /* searching inside encrypted parts doesn't really make sense */
196 g_node_children_foreach(mimeinfo
->node
, G_TRAVERSE_ALL
, msginfo_set_signed_flag
, sstate
);
200 void privacy_msginfo_get_signed_state(MsgInfo
*msginfo
, gchar
**system
)
202 struct SignedState sstate
;
203 MimeInfo
*mimeinfo
= procmime_scan_message(msginfo
);
206 sstate
.msginfo
= msginfo
;
207 sstate
.system
= system
;
208 g_node_children_foreach(mimeinfo
->node
, G_TRAVERSE_ALL
, msginfo_set_signed_flag
, &sstate
);
212 * Check the signature of a MimeInfo. privacy_mimeinfo_is_signed
213 * should be called before otherwise it is done by this function.
214 * If the MimeInfo is not signed an error code will be returned.
216 * \return Error code indicating the result of the check,
217 * < 0 if an error occurred
219 gint
privacy_mimeinfo_check_signature(MimeInfo
*mimeinfo
,
220 GCancellable
*cancellable
,
221 GAsyncReadyCallback callback
,
224 PrivacySystem
*system
;
226 if (mimeinfo
== NULL
)
227 g_error("siginfo was NULL");
229 if (mimeinfo
->privacy
== NULL
) {
230 g_warning("mimeinfo->privacy was NULL");
232 privacy_mimeinfo_is_signed(mimeinfo
);
233 if (mimeinfo
->privacy
== NULL
) {
234 g_error("failed to set up PrivacyData");
238 system
= privacy_data_get_system(mimeinfo
->privacy
);
240 g_error("failed to get privacy system");
241 else if (system
->check_signature
== NULL
)
242 g_error("didn't find check_signature function");
244 return system
->check_signature(mimeinfo
, cancellable
, callback
, user_data
);
247 SignatureStatus
privacy_mimeinfo_get_sig_status(MimeInfo
*mimeinfo
)
249 PrivacySystem
*system
;
251 cm_return_val_if_fail(mimeinfo
!= NULL
, -1);
253 if (mimeinfo
->privacy
== NULL
) {
254 privacy_mimeinfo_is_signed(mimeinfo
);
256 if (mimeinfo
->privacy
== NULL
)
257 return SIGNATURE_UNCHECKED
;
260 system
= privacy_data_get_system(mimeinfo
->privacy
);
262 return SIGNATURE_UNCHECKED
;
264 if (mimeinfo
->sig_data
== NULL
)
265 return SIGNATURE_UNCHECKED
;
267 return mimeinfo
->sig_data
->status
;
270 gchar
*privacy_mimeinfo_get_sig_info(MimeInfo
*mimeinfo
, gboolean full
)
272 PrivacySystem
*system
;
275 cm_return_val_if_fail(mimeinfo
!= NULL
, NULL
);
277 if (mimeinfo
->privacy
== NULL
) {
278 privacy_mimeinfo_is_signed(mimeinfo
);
280 if (mimeinfo
->privacy
== NULL
)
281 return _("No signature found");
284 system
= privacy_data_get_system(mimeinfo
->privacy
);
286 return _("No signature found");
288 if (mimeinfo
->sig_data
== NULL
)
289 return _("No information available");
291 info
= full
? mimeinfo
->sig_data
->info_full
: mimeinfo
->sig_data
->info_short
;
293 return _("No information available");
298 gboolean
privacy_mimeinfo_is_encrypted(MimeInfo
*mimeinfo
)
301 cm_return_val_if_fail(mimeinfo
!= NULL
, FALSE
);
303 for(cur
= systems
; cur
!= NULL
; cur
= g_slist_next(cur
)) {
304 PrivacySystem
*system
= (PrivacySystem
*) cur
->data
;
306 if(system
->is_encrypted
!= NULL
&& system
->is_encrypted(mimeinfo
))
313 static gint
decrypt(MimeInfo
*mimeinfo
, PrivacySystem
*system
)
315 MimeInfo
*decryptedinfo
, *parentinfo
;
318 cm_return_val_if_fail(system
->decrypt
!= NULL
, -1);
320 decryptedinfo
= system
->decrypt(mimeinfo
);
321 if (decryptedinfo
== NULL
)
324 parentinfo
= procmime_mimeinfo_parent(mimeinfo
);
325 childnumber
= g_node_child_index(parentinfo
->node
, mimeinfo
);
327 procmime_mimeinfo_free_all(&mimeinfo
);
329 g_node_insert(parentinfo
->node
, childnumber
, decryptedinfo
->node
);
334 gint
privacy_mimeinfo_decrypt(MimeInfo
*mimeinfo
)
337 cm_return_val_if_fail(mimeinfo
!= NULL
, FALSE
);
339 procmime_decode_content(mimeinfo
);
341 for(cur
= systems
; cur
!= NULL
; cur
= g_slist_next(cur
)) {
342 PrivacySystem
*system
= (PrivacySystem
*) cur
->data
;
344 if(system
->is_encrypted
!= NULL
&& system
->is_encrypted(mimeinfo
))
345 return decrypt(mimeinfo
, system
);
351 GSList
*privacy_get_system_ids()
356 for(cur
= systems
; cur
!= NULL
; cur
= g_slist_next(cur
)) {
357 PrivacySystem
*system
= (PrivacySystem
*) cur
->data
;
359 ret
= g_slist_append(ret
, g_strdup(system
->id
));
365 static PrivacySystem
*privacy_get_system(const gchar
*id
)
369 cm_return_val_if_fail(id
!= NULL
, NULL
);
371 for(cur
= systems
; cur
!= NULL
; cur
= g_slist_next(cur
)) {
372 PrivacySystem
*system
= (PrivacySystem
*) cur
->data
;
374 if(strcmp(id
, system
->id
) == 0)
381 const gchar
*privacy_system_get_name(const gchar
*id
)
383 PrivacySystem
*system
;
385 cm_return_val_if_fail(id
!= NULL
, NULL
);
387 system
= privacy_get_system(id
);
394 gboolean
privacy_system_can_sign(const gchar
*id
)
396 PrivacySystem
*system
;
398 cm_return_val_if_fail(id
!= NULL
, FALSE
);
400 system
= privacy_get_system(id
);
404 return system
->can_sign
;
407 gboolean
privacy_system_can_encrypt(const gchar
*id
)
409 PrivacySystem
*system
;
411 cm_return_val_if_fail(id
!= NULL
, FALSE
);
413 system
= privacy_get_system(id
);
417 return system
->can_encrypt
;
420 gboolean
privacy_sign(const gchar
*id
, MimeInfo
*target
, PrefsAccount
*account
, const gchar
*from_addr
)
422 PrivacySystem
*system
;
424 cm_return_val_if_fail(id
!= NULL
, FALSE
);
425 cm_return_val_if_fail(target
!= NULL
, FALSE
);
427 system
= privacy_get_system(id
);
430 if (!system
->can_sign
)
432 if (system
->sign
== NULL
)
435 return system
->sign(target
, account
, from_addr
);
438 gchar
*privacy_get_encrypt_data(const gchar
*id
, GSList
*recp_names
)
440 PrivacySystem
*system
;
442 GSList
*uniq_names
= NULL
, *cur
;
444 cm_return_val_if_fail(id
!= NULL
, NULL
);
445 cm_return_val_if_fail(recp_names
!= NULL
, NULL
);
447 system
= privacy_get_system(id
);
450 if (!system
->can_encrypt
)
452 if (system
->get_encrypt_data
== NULL
)
455 for (cur
= recp_names
; cur
; cur
= cur
->next
) {
456 if (!g_slist_find_custom(uniq_names
, cur
->data
, (GCompareFunc
)strcmp
)) {
457 uniq_names
= g_slist_prepend(uniq_names
, cur
->data
);
460 ret
= system
->get_encrypt_data(uniq_names
);
462 g_slist_free(uniq_names
);
466 const gchar
*privacy_get_encrypt_warning(const gchar
*id
)
468 PrivacySystem
*system
;
470 cm_return_val_if_fail(id
!= NULL
, NULL
);
472 system
= privacy_get_system(id
);
475 if (!system
->can_encrypt
)
477 if (system
->get_encrypt_warning
== NULL
)
480 return system
->get_encrypt_warning();
483 void privacy_inhibit_encrypt_warning(const gchar
*id
, gboolean inhibit
)
485 PrivacySystem
*system
;
487 cm_return_if_fail(id
!= NULL
);
489 system
= privacy_get_system(id
);
492 if (!system
->can_encrypt
)
494 if (system
->inhibit_encrypt_warning
== NULL
)
497 system
->inhibit_encrypt_warning(inhibit
);
500 gboolean
privacy_encrypt(const gchar
*id
, MimeInfo
*mimeinfo
, const gchar
*encdata
)
502 PrivacySystem
*system
;
504 cm_return_val_if_fail(id
!= NULL
, FALSE
);
505 cm_return_val_if_fail(mimeinfo
!= NULL
, FALSE
);
506 if (encdata
== NULL
) {
507 privacy_set_error(_("No recipient keys defined."));
511 system
= privacy_get_system(id
);
514 if (!system
->can_encrypt
)
516 if (system
->encrypt
== NULL
)
519 return system
->encrypt(mimeinfo
, encdata
);
522 gboolean
privacy_auto_check_signatures(MimeInfo
*mimeinfo
)
524 PrivacySystem
*system
;
526 cm_return_val_if_fail(mimeinfo
!= NULL
, FALSE
);
528 if (mimeinfo
->privacy
== NULL
)
529 privacy_mimeinfo_is_signed(mimeinfo
);
531 if (mimeinfo
->privacy
== NULL
)
534 system
= privacy_data_get_system(mimeinfo
->privacy
);
537 if (system
->auto_check_signatures
== NULL
)
540 return system
->auto_check_signatures();