1 /*
2  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2016 the Claws Mail team
4  *
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.
9  *
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.
14  *
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/>.
17  */
18 
19 #ifdef HAVE_CONFIG_H
20 #  include "config.h"
21 #include "claws-features.h"
22 #endif
23 
24 #ifdef USE_GPGME
25 
26 #include <time.h>
27 #include <gtk/gtk.h>
28 #include <gpgme.h>
29 #include <glib.h>
30 #include <glib/gi18n.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <errno.h>
35 #include <sys/types.h>
36 #ifndef G_OS_WIN32
37 #  include <sys/wait.h>
38 #else
39 #  include <pthread.h>
40 #  include <windows.h>
41 #endif
42 #if (defined(__DragonFly__) || defined(SOLARIS) || defined (__NetBSD__) || defined (__FreeBSD__) || defined (__OpenBSD__))
43 #  include <sys/signal.h>
44 #endif
45 #ifndef G_OS_WIN32
46 #include <sys/mman.h>
47 #endif
48 #if HAVE_LOCALE_H
49 #  include <locale.h>
50 #endif
51 
52 #include "sgpgme.h"
53 #include "privacy.h"
54 #include "prefs_common.h"
55 #include "utils.h"
56 #include "alertpanel.h"
57 #include "passphrase.h"
58 #include "prefs_gpg.h"
59 #include "account.h"
60 #include "select-keys.h"
61 #include "claws.h"
62 #include "file-utils.h"
63 
sgpgme_disable_all(void)64 static void sgpgme_disable_all(void)
65 {
66     /* FIXME: set a flag, so that we don't bother the user with failed
67      * gpgme messages */
68 }
69 
sgpgme_verify_signature(gpgme_ctx_t ctx,gpgme_data_t sig,gpgme_data_t plain,gpgme_data_t dummy)70 gpgme_verify_result_t sgpgme_verify_signature(gpgme_ctx_t ctx, gpgme_data_t sig,
71 					gpgme_data_t plain, gpgme_data_t dummy)
72 {
73 	gpgme_verify_result_t status = NULL;
74 	gpgme_error_t err;
75 
76 	if ((err = gpgme_op_verify(ctx, sig, plain, dummy)) != GPG_ERR_NO_ERROR) {
77 		debug_print("op_verify err %s\n", gpgme_strerror(err));
78 		privacy_set_error("%s", gpgme_strerror(err));
79 		return GINT_TO_POINTER(-GPG_ERR_SYSTEM_ERROR);
80 	}
81 	status = gpgme_op_verify_result(ctx);
82 	if (status && status->signatures == NULL) {
83 		debug_print("no signature found\n");
84 		privacy_set_error(_("No signature found"));
85 		return GINT_TO_POINTER(-GPG_ERR_SYSTEM_ERROR);
86 	}
87 	return status;
88 }
89 
sgpgme_sigstat_gpgme_to_privacy(gpgme_ctx_t ctx,gpgme_verify_result_t status)90 SignatureStatus sgpgme_sigstat_gpgme_to_privacy(gpgme_ctx_t ctx, gpgme_verify_result_t status)
91 {
92 	gpgme_signature_t sig = NULL;
93 
94 	if (GPOINTER_TO_INT(status) == -GPG_ERR_SYSTEM_ERROR) {
95 		debug_print("system error\n");
96 		return SIGNATURE_CHECK_FAILED;
97 	}
98 
99 	if (status == NULL) {
100 		debug_print("status == NULL\n");
101 		return SIGNATURE_UNCHECKED;
102 	}
103 	sig = status->signatures;
104 
105 	if (sig == NULL) {
106 		debug_print("sig == NULL\n");
107 		return SIGNATURE_UNCHECKED;
108 	}
109 
110 	debug_print("err code %d\n", gpg_err_code(sig->status));
111 	switch (gpg_err_code(sig->status)) {
112 	case GPG_ERR_NO_ERROR:
113 		switch (sig->validity) {
114 		case GPGME_VALIDITY_NEVER:
115 			return SIGNATURE_INVALID;
116 		case GPGME_VALIDITY_UNKNOWN:
117 		case GPGME_VALIDITY_UNDEFINED:
118 		case GPGME_VALIDITY_MARGINAL:
119 		case GPGME_VALIDITY_FULL:
120 		case GPGME_VALIDITY_ULTIMATE:
121 			return SIGNATURE_OK;
122 		default:
123 			return SIGNATURE_CHECK_FAILED;
124 		}
125 	case GPG_ERR_SIG_EXPIRED:
126 	case GPG_ERR_CERT_REVOKED:
127 		return SIGNATURE_WARN;
128 	case GPG_ERR_KEY_EXPIRED:
129 		return SIGNATURE_KEY_EXPIRED;
130 	case GPG_ERR_BAD_SIGNATURE:
131 		return SIGNATURE_INVALID;
132 	case GPG_ERR_NO_PUBKEY:
133 		return SIGNATURE_CHECK_FAILED;
134 	default:
135 		return SIGNATURE_CHECK_FAILED;
136 	}
137 	return SIGNATURE_CHECK_FAILED;
138 }
139 
get_validity_str(unsigned long validity)140 static const gchar *get_validity_str(unsigned long validity)
141 {
142 	switch (gpg_err_code(validity)) {
143 	case GPGME_VALIDITY_UNKNOWN:
144 		return _("Unknown");
145 	case GPGME_VALIDITY_UNDEFINED:
146 		return _("Undefined");
147 	case GPGME_VALIDITY_NEVER:
148 		return _("Never");
149 	case GPGME_VALIDITY_MARGINAL:
150 		return _("Marginal");
151 	case GPGME_VALIDITY_FULL:
152 		return _("Full");
153 	case GPGME_VALIDITY_ULTIMATE:
154 		return _("Ultimate");
155 	default:
156 		return _("Error");
157 	}
158 }
159 
get_owner_trust_str(unsigned long owner_trust)160 static const gchar *get_owner_trust_str(unsigned long owner_trust)
161 {
162 	switch (gpgme_err_code(owner_trust)) {
163 	case GPGME_VALIDITY_NEVER:
164 		return _("Untrusted");
165 	case GPGME_VALIDITY_MARGINAL:
166 		return _("Marginal");
167 	case GPGME_VALIDITY_FULL:
168 		return _("Full");
169 	case GPGME_VALIDITY_ULTIMATE:
170 		return _("Ultimate");
171 	default:
172 		return _("Unknown");
173 	}
174 }
175 
get_gpg_executable_name()176 gchar *get_gpg_executable_name()
177 {
178 	gpgme_engine_info_t e;
179 
180 	if (!gpgme_get_engine_info(&e)) {
181 		while (e != NULL) {
182 			if (e->protocol == GPGME_PROTOCOL_OpenPGP
183 					&& e->file_name != NULL) {
184 				debug_print("Found gpg executable: '%s'\n", e->file_name);
185 				return e->file_name;
186 			}
187 		}
188 	}
189 
190 	return NULL;
191 }
192 
get_gpg_version_string()193 static gchar *get_gpg_version_string()
194 {
195 	gpgme_engine_info_t e;
196 
197 	if (!gpgme_get_engine_info(&e)) {
198 		while (e != NULL) {
199 			if (e->protocol == GPGME_PROTOCOL_OpenPGP
200 					&& e->version != NULL) {
201 				debug_print("Got OpenPGP version: '%s'\n", e->version);
202 				return e->version;
203 			}
204 		}
205 	}
206 
207 	return NULL;
208 }
209 
extract_name(const char * uid)210 static gchar *extract_name(const char *uid)
211 {
212 	if (uid == NULL)
213 		return NULL;
214 	if (!strncmp(uid, "CN=", 3)) {
215 		gchar *result = g_strdup(uid+3);
216 		if (strstr(result, ","))
217 			*(strstr(result, ",")) = '\0';
218 		return result;
219 	} else if (strstr(uid, ",CN=")) {
220 		gchar *result = g_strdup(strstr(uid, ",CN=")+4);
221 		if (strstr(result, ","))
222 			*(strstr(result, ",")) = '\0';
223 		return result;
224 	} else {
225 		return g_strdup(uid);
226 	}
227 }
sgpgme_sigstat_info_short(gpgme_ctx_t ctx,gpgme_verify_result_t status)228 gchar *sgpgme_sigstat_info_short(gpgme_ctx_t ctx, gpgme_verify_result_t status)
229 {
230 	gpgme_signature_t sig = NULL;
231 	gchar *uname = NULL;
232 	gpgme_key_t key;
233 	gchar *result = NULL;
234 	gpgme_error_t err = 0;
235 	static gboolean warned = FALSE;
236 
237 	if (GPOINTER_TO_INT(status) == -GPG_ERR_SYSTEM_ERROR) {
238 		return g_strdup_printf(_("The signature can't be checked - %s"), privacy_get_error());
239 	}
240 
241 	if (status == NULL) {
242 		return g_strdup(_("The signature has not been checked."));
243 	}
244 	sig = status->signatures;
245 	if (sig == NULL) {
246 		return g_strdup(_("The signature has not been checked."));
247 	}
248 
249 	err = gpgme_get_key(ctx, sig->fpr, &key, 0);
250 	if (gpg_err_code(err) == GPG_ERR_NO_AGENT) {
251 		if (!warned)
252 			alertpanel_error(_("PGP Core: Can't get key - no gpg-agent running."));
253 		else
254 			g_warning("PGP Core: Can't get key - no gpg-agent running.");
255 		warned = TRUE;
256 	} else if (gpg_err_code(err) != GPG_ERR_NO_ERROR && gpg_err_code(err) != GPG_ERR_EOF) {
257 		return g_strdup_printf(_("The signature can't be checked - %s"),
258 			gpgme_strerror(err));
259   }
260 
261 	if (key)
262 		uname = extract_name(key->uids->uid);
263 	else
264 		uname = g_strdup("<?>");
265 
266 	switch (gpg_err_code(sig->status)) {
267 	case GPG_ERR_NO_ERROR:
268                switch ((key && key->uids) ? key->uids->validity : GPGME_VALIDITY_UNKNOWN) {
269 		case GPGME_VALIDITY_ULTIMATE:
270 			result = g_strdup_printf(_("Good signature from \"%s\" [ultimate]"), uname);
271 			break;
272 		case GPGME_VALIDITY_FULL:
273 			result = g_strdup_printf(_("Good signature from \"%s\" [full]"), uname);
274 			break;
275 		case GPGME_VALIDITY_MARGINAL:
276 			result = g_strdup_printf(_("Good signature from \"%s\" [marginal]"), uname);
277 			break;
278 		case GPGME_VALIDITY_UNKNOWN:
279 		case GPGME_VALIDITY_UNDEFINED:
280 		case GPGME_VALIDITY_NEVER:
281 		default:
282 			if (key) {
283 				result = g_strdup_printf(_("Good signature from \"%s\""), uname);
284 			} else {
285 				result = g_strdup_printf(_("Key 0x%s not available to verify this signature"), sig->fpr);
286 			}
287 			break;
288                }
289 		break;
290 	case GPG_ERR_SIG_EXPIRED:
291 		result = g_strdup_printf(_("Expired signature from \"%s\""), uname);
292 		break;
293 	case GPG_ERR_KEY_EXPIRED:
294 		result = g_strdup_printf(_("Good signature from \"%s\", but the key has expired"), uname);
295 		break;
296 	case GPG_ERR_CERT_REVOKED:
297 		result = g_strdup_printf(_("Good signature from \"%s\", but the key has been revoked"), uname);
298 		break;
299 	case GPG_ERR_BAD_SIGNATURE:
300 		result = g_strdup_printf(_("Bad signature from \"%s\""), uname);
301 		break;
302 	case GPG_ERR_NO_PUBKEY: {
303 		result = g_strdup_printf(_("Key 0x%s not available to verify this signature"), sig->fpr);
304 		break;
305 		}
306 	default:
307 		result = g_strdup(_("The signature has not been checked"));
308 		break;
309 	}
310 	if (result == NULL)
311 		result = g_strdup(_("Error"));
312 	g_free(uname);
313 
314 	if (key)
315 		gpgme_key_release(key);
316 
317 	return result;
318 }
319 
sgpgme_sigstat_info_full(gpgme_ctx_t ctx,gpgme_verify_result_t status)320 gchar *sgpgme_sigstat_info_full(gpgme_ctx_t ctx, gpgme_verify_result_t status)
321 {
322 	gint i = 0;
323 	gchar *ret;
324 	GString *siginfo;
325 	gpgme_signature_t sig = NULL;
326 
327 	siginfo = g_string_sized_new(64);
328 	if (status == NULL) {
329 		g_string_append_printf(siginfo,
330 			_("Error checking signature: no status\n"));
331 		goto bail;
332 	 }
333 
334 	sig = status->signatures;
335 
336 	while (sig) {
337 		char buf[100];
338 		struct tm lt;
339 		gpgme_key_t key;
340 		gpgme_error_t err;
341 		const gchar *keytype, *keyid, *uid;
342 
343 		err = gpgme_get_key(ctx, sig->fpr, &key, 0);
344 
345 		if (err != GPG_ERR_NO_ERROR) {
346 			key = NULL;
347 			g_string_append_printf(siginfo,
348 				_("Error checking signature: %s\n"),
349 				gpgme_strerror(err));
350 			goto bail;
351 		}
352 		if (key) {
353 			keytype = gpgme_pubkey_algo_name(
354 					key->subkeys->pubkey_algo);
355 			keyid = key->subkeys->keyid;
356 			uid = key->uids->uid;
357 		} else {
358 			keytype = "?";
359 			keyid = "?";
360 			uid = "?";
361 		}
362 
363 		memset(buf, 0, sizeof(buf));
364 		fast_strftime(buf, sizeof(buf)-1, prefs_common_get_prefs()->date_format, localtime_r((time_t *)&sig->timestamp, &lt));
365 		g_string_append_printf(siginfo,
366 			_("Signature made on %s using %s key ID %s\n"),
367 			buf, keytype, keyid);
368 
369 		switch (gpg_err_code(sig->status)) {
370 		case GPG_ERR_NO_ERROR:
371 			g_string_append_printf(siginfo,
372 				_("Good signature from uid \"%s\" (Validity: %s)\n"),
373 				uid, get_validity_str((key && key->uids) ? key->uids->validity:GPGME_VALIDITY_UNKNOWN));
374 			break;
375 		case GPG_ERR_KEY_EXPIRED:
376 			g_string_append_printf(siginfo,
377 				_("Expired key uid \"%s\"\n"),
378 				uid);
379 			break;
380 		case GPG_ERR_SIG_EXPIRED:
381 			g_string_append_printf(siginfo,
382 				_("Expired signature from uid \"%s\" (Validity: %s)\n"),
383 				uid, get_validity_str((key && key->uids) ? key->uids->validity:GPGME_VALIDITY_UNKNOWN));
384 			break;
385 		case GPG_ERR_CERT_REVOKED:
386 			g_string_append_printf(siginfo,
387 				_("Revoked key uid \"%s\"\n"),
388 				uid);
389 			break;
390 		case GPG_ERR_BAD_SIGNATURE:
391 			g_string_append_printf(siginfo,
392 				_("BAD signature from \"%s\"\n"),
393 				uid);
394 			break;
395 		default:
396 			break;
397 		}
398 		if (sig->status != GPG_ERR_BAD_SIGNATURE) {
399 			gint j = 1;
400 			if (key) {
401 				key->uids = key->uids ? key->uids->next : NULL;
402 				while (key->uids != NULL) {
403 					g_string_append_printf(siginfo,
404 						g_strconcat("                    ",
405 							    _("uid \"%s\" (Validity: %s)\n"), NULL),
406 						key->uids->uid,
407 						key->uids->revoked==TRUE?_("Revoked"):get_validity_str(key->uids->validity));
408 					j++;
409 					key->uids = key->uids->next;
410 				}
411 			}
412 			g_string_append_printf(siginfo,_("Owner Trust: %s\n"),
413 					       key ? get_owner_trust_str(key->owner_trust) : _("No key!"));
414 			g_string_append(siginfo,
415 				_("Primary key fingerprint:"));
416 			const char* primary_fpr = NULL;
417 			if (key && key->subkeys && key->subkeys->fpr)
418 				primary_fpr = key->subkeys->fpr;
419 			else
420 				g_string_append(siginfo, " ?");
421 			int idx; /* now pretty-print the fingerprint */
422 			for (idx=0; primary_fpr && *primary_fpr!='\0'; idx++, primary_fpr++) {
423 				if (idx%4==0)
424 					g_string_append_c(siginfo, ' ');
425 				if (idx%20==0)
426 					g_string_append_c(siginfo, ' ');
427 				g_string_append_c(siginfo, (gchar)*primary_fpr);
428 			}
429 			g_string_append_c(siginfo, '\n');
430 #ifdef HAVE_GPGME_PKA_TRUST
431                         if (sig->pka_trust == 1 && sig->pka_address) {
432                                 g_string_append_printf(siginfo,
433                                    _("WARNING: Signer's address \"%s\" "
434                                       "does not match DNS entry\n"),
435                                    sig->pka_address);
436                         }
437                         else if (sig->pka_trust == 2 && sig->pka_address) {
438                                 g_string_append_printf(siginfo,
439                                    _("Verified signer's address is \"%s\"\n"),
440                                    sig->pka_address);
441                                 /* FIXME: Compare the address to the
442                                  * From: address.  */
443                         }
444 #endif /*HAVE_GPGME_PKA_TRUST*/
445 		}
446 
447 		g_string_append(siginfo, "\n");
448 		i++;
449 		sig = sig->next;
450 	}
451 bail:
452 	ret = siginfo->str;
453 	g_string_free(siginfo, FALSE);
454 	return ret;
455 }
456 
sgpgme_data_from_mimeinfo(MimeInfo * mimeinfo)457 gpgme_data_t sgpgme_data_from_mimeinfo(MimeInfo *mimeinfo)
458 {
459 	gpgme_data_t data = NULL;
460 	gpgme_error_t err;
461 	FILE *fp = claws_fopen(mimeinfo->data.filename, "rb");
462 
463 	if (!fp)
464 		return NULL;
465 
466 	err = gpgme_data_new_from_filepart(&data, NULL, fp, mimeinfo->offset, mimeinfo->length);
467 	claws_fclose(fp);
468 
469 	debug_print("data %p (%d %d)\n", (void *)&data, mimeinfo->offset, mimeinfo->length);
470 	if (err) {
471 		debug_print ("gpgme_data_new_from_file failed: %s\n",
472 			     gpgme_strerror (err));
473 		privacy_set_error(_("Couldn't get data from message, %s"), gpgme_strerror(err));
474 		return NULL;
475 	}
476 	return data;
477 }
478 
sgpgme_decrypt_verify(gpgme_data_t cipher,gpgme_verify_result_t * status,gpgme_ctx_t ctx)479 gpgme_data_t sgpgme_decrypt_verify(gpgme_data_t cipher, gpgme_verify_result_t *status, gpgme_ctx_t ctx)
480 {
481 	struct passphrase_cb_info_s info;
482 	gpgme_data_t plain;
483 	gpgme_error_t err;
484 
485 	memset (&info, 0, sizeof info);
486 
487 	if ((err = gpgme_data_new(&plain)) != GPG_ERR_NO_ERROR) {
488 		gpgme_release(ctx);
489 		privacy_set_error(_("Couldn't initialize data, %s"), gpgme_strerror(err));
490 		return NULL;
491 	}
492 
493 	if (gpgme_get_protocol(ctx) == GPGME_PROTOCOL_OpenPGP) {
494 		prefs_gpg_enable_agent(prefs_gpg_get_config()->use_gpg_agent);
495 		if (!g_getenv("GPG_AGENT_INFO") || !prefs_gpg_get_config()->use_gpg_agent) {
496         		info.c = ctx;
497         		gpgme_set_passphrase_cb (ctx, gpgmegtk_passphrase_cb, &info);
498     		}
499 	} else {
500 		prefs_gpg_enable_agent(TRUE);
501         	info.c = ctx;
502         	gpgme_set_passphrase_cb (ctx, NULL, &info);
503 	}
504 
505 
506 	if (gpgme_get_protocol(ctx) == GPGME_PROTOCOL_OpenPGP) {
507 		err = gpgme_op_decrypt_verify(ctx, cipher, plain);
508 		if (err != GPG_ERR_NO_ERROR) {
509 			debug_print("can't decrypt (%s)\n", gpgme_strerror(err));
510 			privacy_set_error("%s", gpgme_strerror(err));
511 			gpgmegtk_free_passphrase();
512 			gpgme_data_release(plain);
513 			return NULL;
514 		}
515 
516 		err = cm_gpgme_data_rewind(plain);
517 		if (err) {
518 			debug_print("can't seek (%d %d %s)\n", err, errno, g_strerror(errno));
519 		}
520 
521 		debug_print("decrypted.\n");
522 		*status = gpgme_op_verify_result (ctx);
523 	} else {
524 		err = gpgme_op_decrypt(ctx, cipher, plain);
525 		if (err != GPG_ERR_NO_ERROR) {
526 			debug_print("can't decrypt (%s)\n", gpgme_strerror(err));
527 			privacy_set_error("%s", gpgme_strerror(err));
528 			gpgmegtk_free_passphrase();
529 			gpgme_data_release(plain);
530 			return NULL;
531 		}
532 
533 		err = cm_gpgme_data_rewind(plain);
534 		if (err) {
535 			debug_print("can't seek (%d %d %s)\n", err, errno, g_strerror(errno));
536 		}
537 
538 		debug_print("decrypted.\n");
539 		*status = gpgme_op_verify_result (ctx);
540 	}
541 	return plain;
542 }
543 
sgpgme_get_encrypt_data(GSList * recp_names,gpgme_protocol_t proto)544 gchar *sgpgme_get_encrypt_data(GSList *recp_names, gpgme_protocol_t proto)
545 {
546 	SelectionResult result = KEY_SELECTION_CANCEL;
547 	gpgme_key_t *keys = gpgmegtk_recipient_selection(recp_names, &result,
548 				proto);
549 	gchar *ret = NULL;
550 	int i = 0;
551 
552 	if (!keys) {
553 		if (result == KEY_SELECTION_DONT)
554 			return g_strdup("_DONT_ENCRYPT_");
555 		else
556 			return NULL;
557 	}
558 	while (keys[i]) {
559 		gpgme_subkey_t skey = keys[i]->subkeys;
560 		gchar *fpr = skey->fpr;
561 		gchar *tmp = NULL;
562 		debug_print("adding %s\n", fpr);
563 		tmp = g_strconcat(ret?ret:"", fpr, " ", NULL);
564 		g_free(ret);
565 		ret = tmp;
566 		i++;
567 	}
568 	return ret;
569 }
570 
sgpgme_setup_signers(gpgme_ctx_t ctx,PrefsAccount * account,const gchar * from_addr)571 gboolean sgpgme_setup_signers(gpgme_ctx_t ctx, PrefsAccount *account,
572 			      const gchar *from_addr)
573 {
574 	GPGAccountConfig *config;
575 	const gchar *signer_addr = account->address;
576 	SignKeyType sk;
577 	gchar *skid;
578 	gboolean smime = FALSE;
579 
580 	gpgme_signers_clear(ctx);
581 
582 	if (gpgme_get_protocol(ctx) == GPGME_PROTOCOL_CMS)
583 		smime = TRUE;
584 
585 	if (from_addr)
586 		signer_addr = from_addr;
587 	config = prefs_gpg_account_get_config(account);
588 
589 	if(smime) {
590 		debug_print("sgpgme_setup_signers: S/MIME protocol\n");
591 		sk = config->smime_sign_key;
592 		skid = config->smime_sign_key_id;
593 	} else {
594 		debug_print("sgpgme_setup_signers: OpenPGP protocol\n");
595 		sk = config->sign_key;
596 		skid = config->sign_key_id;
597 	}
598 
599 	switch(sk) {
600 	case SIGN_KEY_DEFAULT:
601 		debug_print("using default gnupg key\n");
602 		break;
603 	case SIGN_KEY_BY_FROM:
604 		debug_print("using key for %s\n", signer_addr);
605 		break;
606 	case SIGN_KEY_CUSTOM:
607 		debug_print("using key for %s\n", skid);
608 		break;
609 	}
610 
611 	if (sk != SIGN_KEY_DEFAULT) {
612 		const gchar *keyid;
613 		gpgme_key_t key, found_key;
614 		gpgme_error_t err;
615 
616 		if (sk == SIGN_KEY_BY_FROM)
617 			keyid = signer_addr;
618 		else if (sk == SIGN_KEY_CUSTOM)
619 			keyid = skid;
620 		else
621 			goto bail;
622 
623                 found_key = NULL;
624 		/* Look for any key, not just private ones, or GPGMe doesn't
625 		 * correctly set the revoked flag. */
626 		err = gpgme_op_keylist_start(ctx, keyid, 0);
627 		while (err == 0) {
628 			if ((err = gpgme_op_keylist_next(ctx, &key)) != 0)
629 				break;
630 
631 			if (key == NULL)
632 				continue;
633 
634 			if (!key->can_sign) {
635 				debug_print("skipping a key, can not be used for signing\n");
636 				gpgme_key_unref(key);
637 				continue;
638 			}
639 
640 			if (key->protocol != gpgme_get_protocol(ctx)) {
641 				debug_print("skipping a key (wrong protocol %d)\n", key->protocol);
642 				gpgme_key_unref(key);
643 				continue;
644 			}
645 
646 			if (key->expired) {
647 				debug_print("skipping a key, expired\n");
648 				gpgme_key_unref(key);
649 				continue;
650 			}
651 			if (key->revoked) {
652 				debug_print("skipping a key, revoked\n");
653 				gpgme_key_unref(key);
654 				continue;
655 			}
656 			if (key->disabled) {
657 				debug_print("skipping a key, disabled\n");
658 				gpgme_key_unref(key);
659 				continue;
660 			}
661 
662 			if (found_key != NULL) {
663 				gpgme_key_unref(key);
664 				gpgme_op_keylist_end(ctx);
665 				g_warning("ambiguous specification of secret key '%s'", keyid);
666 				privacy_set_error(_("Secret key specification is ambiguous"));
667 				goto bail;
668 			}
669 
670 			found_key = key;
671 		}
672 		gpgme_op_keylist_end(ctx);
673 
674 		if (found_key == NULL) {
675 			g_warning("setup_signers start: %s", gpgme_strerror(err));
676 			privacy_set_error(_("Secret key not found (%s)"), gpgme_strerror(err));
677 			goto bail;
678                 }
679 
680 		err = gpgme_signers_add(ctx, found_key);
681 		debug_print("got key (proto %d (pgp %d, smime %d).\n",
682 			    found_key->protocol, GPGME_PROTOCOL_OpenPGP,
683 			    GPGME_PROTOCOL_CMS);
684 		gpgme_key_unref(found_key);
685 
686 		if (err) {
687 			g_warning("error adding secret key: %s",
688 				  gpgme_strerror(err));
689 			privacy_set_error(_("Error setting secret key: %s"),
690 					  gpgme_strerror(err));
691 			goto bail;
692 		}
693         }
694 
695 	prefs_gpg_account_free_config(config);
696 
697 	return TRUE;
698 bail:
699 	prefs_gpg_account_free_config(config);
700 	return FALSE;
701 }
702 
sgpgme_init()703 void sgpgme_init()
704 {
705 	gchar *ctype_locale = NULL, *messages_locale = NULL;
706 	gchar *ctype_utf8_locale = NULL, *messages_utf8_locale = NULL;
707 	gpgme_error_t err = 0;
708 
709 	gpgme_engine_info_t engineInfo;
710 
711 	if (strcmp(prefs_gpg_get_config()->gpg_path, "") != 0
712 	    && access(prefs_gpg_get_config()->gpg_path, X_OK) != -1) {
713 		err = gpgme_set_engine_info(GPGME_PROTOCOL_OpenPGP, prefs_gpg_get_config()->gpg_path, NULL);
714 		if (err != GPG_ERR_NO_ERROR)
715 			g_warning("failed to set crypto engine configuration: %s", gpgme_strerror(err));
716 	}
717 
718 	if (gpgme_check_version("1.0.0")) {
719 #ifdef LC_CTYPE
720 		debug_print("setting gpgme CTYPE locale\n");
721 #ifdef G_OS_WIN32
722 		ctype_locale = g_win32_getlocale();
723 #else
724 		ctype_locale = g_strdup(setlocale(LC_CTYPE, NULL));
725 #endif
726 		if (ctype_locale) {
727 			debug_print("setting gpgme CTYPE locale to: %s\n", ctype_locale);
728 			if (strchr(ctype_locale, '.'))
729 				*(strchr(ctype_locale, '.')) = '\0';
730 			else if (strchr(ctype_locale, '@'))
731 				*(strchr(ctype_locale, '@')) = '\0';
732 			ctype_utf8_locale = g_strconcat(ctype_locale, ".UTF-8", NULL);
733 
734 			debug_print("setting gpgme locale to UTF8: %s\n", ctype_utf8_locale ? ctype_utf8_locale : "NULL");
735 			gpgme_set_locale(NULL, LC_CTYPE, ctype_utf8_locale);
736 
737 			debug_print("done\n");
738 			g_free(ctype_utf8_locale);
739 			g_free(ctype_locale);
740 		} else {
741 			debug_print("couldn't set gpgme CTYPE locale\n");
742 		}
743 #endif
744 #ifdef LC_MESSAGES
745 		debug_print("setting gpgme MESSAGES locale\n");
746 #ifdef G_OS_WIN32
747 		messages_locale = g_win32_getlocale();
748 #else
749 		messages_locale = g_strdup(setlocale(LC_MESSAGES, NULL));
750 #endif
751 		if (messages_locale) {
752 			debug_print("setting gpgme MESSAGES locale to: %s\n", messages_locale);
753 			if (strchr(messages_locale, '.'))
754 				*(strchr(messages_locale, '.')) = '\0';
755 			else if (strchr(messages_locale, '@'))
756 				*(strchr(messages_locale, '@')) = '\0';
757 			messages_utf8_locale = g_strconcat(messages_locale, ".UTF-8", NULL);
758 			debug_print("setting gpgme locale to UTF8: %s\n", messages_utf8_locale ? messages_utf8_locale : "NULL");
759 
760 			gpgme_set_locale(NULL, LC_MESSAGES, messages_utf8_locale);
761 
762 			debug_print("done\n");
763 			g_free(messages_utf8_locale);
764 			g_free(messages_locale);
765 		} else {
766 			debug_print("couldn't set gpgme MESSAGES locale\n");
767 		}
768 #endif
769 		if (!gpgme_get_engine_info(&engineInfo)) {
770 			while (engineInfo) {
771 				debug_print("GpgME Protocol: %s\n"
772 					    "Version: %s (req %s)\n"
773 					    "Executable: %s\n",
774 					gpgme_get_protocol_name(engineInfo->protocol) ? gpgme_get_protocol_name(engineInfo->protocol):"???",
775 					engineInfo->version ? engineInfo->version:"???",
776 					engineInfo->req_version ? engineInfo->req_version:"???",
777 					engineInfo->file_name ? engineInfo->file_name:"???");
778 				if (engineInfo->protocol == GPGME_PROTOCOL_OpenPGP
779 				&&  gpgme_engine_check_version(engineInfo->protocol) !=
780 					GPG_ERR_NO_ERROR) {
781 					if (engineInfo->file_name && !engineInfo->version) {
782 						alertpanel_error(_("Gpgme protocol '%s' is unusable: "
783 								   "Engine '%s' isn't installed properly."),
784 								   gpgme_get_protocol_name(engineInfo->protocol),
785 								   engineInfo->file_name);
786 					} else if (engineInfo->file_name && engineInfo->version
787 					  && engineInfo->req_version) {
788 						alertpanel_error(_("Gpgme protocol '%s' is unusable: "
789 								   "Engine '%s' version %s is installed, "
790 								   "but version %s is required.\n"),
791 								   gpgme_get_protocol_name(engineInfo->protocol),
792 								   engineInfo->file_name,
793 								   engineInfo->version,
794 								   engineInfo->req_version);
795 					} else {
796 						alertpanel_error(_("Gpgme protocol '%s' is unusable "
797 								   "(unknown problem)"),
798 								   gpgme_get_protocol_name(engineInfo->protocol));
799 					}
800 				}
801 				engineInfo = engineInfo->next;
802 			}
803 		}
804 	} else {
805 		sgpgme_disable_all();
806 
807 		if (prefs_gpg_get_config()->gpg_warning) {
808 			AlertValue val;
809 
810 			val = alertpanel_full
811 				(_("Warning"),
812 				 _("GnuPG is not installed properly, or needs "
813 				 "to be upgraded.\n"
814 				 "OpenPGP support disabled."),
815 				 GTK_STOCK_CLOSE, NULL, NULL, ALERTFOCUS_FIRST, TRUE, NULL,
816 				 ALERT_WARNING);
817 			if (val & G_ALERTDISABLE)
818 				prefs_gpg_get_config()->gpg_warning = FALSE;
819 		}
820 	}
821 }
822 
sgpgme_done()823 void sgpgme_done()
824 {
825         gpgmegtk_free_passphrase();
826 }
827 
828 #ifdef G_OS_WIN32
829 struct _ExportCtx {
830 	gboolean done;
831 	gchar *cmd;
832 	DWORD exitcode;
833 };
834 
_export_threaded(void * arg)835 static void *_export_threaded(void *arg)
836 {
837 	struct _ExportCtx *ctx = (struct _ExportCtx *)arg;
838 	gboolean result;
839 
840 	PROCESS_INFORMATION pi = {0};
841 	STARTUPINFO si = {0};
842 
843 	result = CreateProcess(NULL, ctx->cmd, NULL, NULL, FALSE,
844 			NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW,
845 			NULL, NULL, &si, &pi);
846 
847 	if (!result) {
848 		debug_print("Couldn't execute '%s'\n", ctx->cmd);
849 	} else {
850 		WaitForSingleObject(pi.hProcess, 10000);
851 		result = GetExitCodeProcess(pi.hProcess, &ctx->exitcode);
852 		if (ctx->exitcode == STILL_ACTIVE) {
853 			debug_print("Process still running, terminating it.\n");
854 			TerminateProcess(pi.hProcess, 255);
855 		}
856 
857 		CloseHandle(pi.hProcess);
858 		CloseHandle(pi.hThread);
859 
860 		if (!result) {
861 			debug_print("Process executed, but we couldn't get its exit code (huh?)\n");
862 		}
863 	}
864 
865 	ctx->done = TRUE;
866 	return NULL;
867 }
868 #endif
869 
sgpgme_create_secret_key(PrefsAccount * account,gboolean ask_create)870 void sgpgme_create_secret_key(PrefsAccount *account, gboolean ask_create)
871 {
872 	AlertValue val = G_ALERTDEFAULT;
873 	gchar *key_parms = NULL;
874 	gchar *name = NULL;
875 	gchar *email = NULL;
876 	gchar *passphrase = NULL, *passphrase_second = NULL;
877 	gint prev_bad = 0;
878 	gchar *tmp = NULL, *gpgver;
879 	gpgme_error_t err = 0;
880 	gpgme_ctx_t ctx;
881 	GtkWidget *window = NULL;
882 	gpgme_genkey_result_t key;
883 	gboolean exported = FALSE;
884 
885 	if (account == NULL)
886 		account = account_get_default();
887 
888 	if (account->address == NULL) {
889 		alertpanel_error(_("You have to save the account's information with \"OK\" "
890 				   "before being able to generate a key pair.\n"));
891 		return;
892 	}
893 	if (ask_create) {
894 		val = alertpanel(_("No PGP key found"),
895 				_("Claws Mail did not find a secret PGP key, "
896 				  "which means that you won't be able to sign "
897 				  "emails or receive encrypted emails.\n"
898 				  "Do you want to create a new key pair now?"),
899 				  GTK_STOCK_NO, GTK_STOCK_YES, NULL, ALERTFOCUS_SECOND);
900 		if (val == G_ALERTDEFAULT) {
901 			return;
902 		}
903 	}
904 
905 	if (account->name) {
906 		name = g_strdup(account->name);
907 	} else {
908 		name = g_strdup(account->address);
909 	}
910 	email = g_strdup(account->address);
911 	tmp = g_strdup_printf("%s <%s>", account->name?account->name:account->address, account->address);
912 	gpgver = get_gpg_version_string();
913 	if (gpgver == NULL || !strncmp(gpgver, "1.", 2)) {
914 		debug_print("Using gpg 1.x, using builtin passphrase dialog.\n");
915 again:
916 		passphrase = passphrase_mbox(tmp, NULL, prev_bad, 1);
917 		if (passphrase == NULL) {
918 			g_free(tmp);
919 			g_free(email);
920 			g_free(name);
921 			return;
922 		}
923 		passphrase_second = passphrase_mbox(tmp, NULL, 0, 2);
924 		if (passphrase_second == NULL) {
925 			g_free(tmp);
926 			g_free(email);
927 			if (passphrase != NULL) {
928 				memset(passphrase, 0, strlen(passphrase));
929 				g_free(passphrase);
930 			}
931 			g_free(name);
932 			return;
933 		}
934 		if (strcmp(passphrase, passphrase_second)) {
935 			if (passphrase != NULL) {
936 				memset(passphrase, 0, strlen(passphrase));
937 				g_free(passphrase);
938 			}
939 			if (passphrase_second != NULL) {
940 				memset(passphrase_second, 0, strlen(passphrase_second));
941 				g_free(passphrase_second);
942 			}
943 			prev_bad = 1;
944 			goto again;
945 		}
946 	}
947 
948 	key_parms = g_strdup_printf("<GnupgKeyParms format=\"internal\">\n"
949 					"Key-Type: RSA\n"
950 					"Key-Length: 2048\n"
951 					"Subkey-Type: RSA\n"
952 					"Subkey-Length: 2048\n"
953 					"Name-Real: %s\n"
954 					"Name-Email: %s\n"
955 					"Expire-Date: 0\n"
956 					"%s%s%s"
957 					"</GnupgKeyParms>\n",
958 					name, email,
959 					passphrase?"Passphrase: ":"",
960 					passphrase?passphrase:"",
961 					passphrase?"\n":"");
962 #ifndef G_PLATFORM_WIN32
963 	if (passphrase &&
964 			mlock(passphrase, strlen(passphrase)) == -1)
965 		debug_print("couldn't lock passphrase\n");
966 	if (passphrase_second &&
967 			mlock(passphrase_second, strlen(passphrase_second)) == -1)
968 		debug_print("couldn't lock passphrase2\n");
969 #endif
970 	g_free(tmp);
971 	g_free(email);
972 	g_free(name);
973 	if (passphrase_second != NULL) {
974 		memset(passphrase_second, 0, strlen(passphrase_second));
975 		g_free(passphrase_second);
976 	}
977 	if (passphrase != NULL) {
978 		memset(passphrase, 0, strlen(passphrase));
979 		g_free(passphrase);
980 	}
981 
982 	err = gpgme_new (&ctx);
983 	if (err) {
984 		alertpanel_error(_("Couldn't generate a new key pair: %s"),
985 				 gpgme_strerror(err));
986 		if (key_parms != NULL) {
987 			memset(key_parms, 0, strlen(key_parms));
988 			g_free(key_parms);
989 		}
990 		return;
991 	}
992 
993 
994 	window = label_window_create(_("Generating your new key pair... Please move the mouse "
995 			      "around to help generate entropy..."));
996 
997 	err = gpgme_op_genkey(ctx, key_parms, NULL, NULL);
998 	if (key_parms != NULL) {
999 		memset(key_parms, 0, strlen(key_parms));
1000 		g_free(key_parms);
1001 	}
1002 
1003 	label_window_destroy(window);
1004 
1005 	if (err) {
1006 		alertpanel_error(_("Couldn't generate a new key pair: %s"), gpgme_strerror(err));
1007 		gpgme_release(ctx);
1008 		return;
1009 	}
1010 	key = gpgme_op_genkey_result(ctx);
1011 	if (key == NULL) {
1012 		alertpanel_error(_("Couldn't generate a new key pair: unknown error"));
1013 		gpgme_release(ctx);
1014 		return;
1015 	} else {
1016 		gchar *buf = g_strdup_printf(_("Your new key pair has been generated. "
1017 				    "Its fingerprint is:\n%s\n\nDo you want to export it "
1018 				    "to a keyserver?"),
1019 				    key->fpr ? key->fpr:"null");
1020 		AlertValue val = alertpanel(_("Key generated"), buf,
1021 				  GTK_STOCK_NO, GTK_STOCK_YES, NULL, ALERTFOCUS_SECOND);
1022 		g_free(buf);
1023 		if (val == G_ALERTALTERNATE) {
1024 			gchar *gpgbin = get_gpg_executable_name();
1025 			gchar *cmd = g_strdup_printf("\"%s\" --batch --no-tty --send-keys %s",
1026 				(gpgbin ? gpgbin : "gpg"), key->fpr);
1027 			debug_print("Executing command: %s\n", cmd);
1028 
1029 #ifndef G_OS_WIN32
1030 			int res = 0;
1031 			pid_t pid = 0;
1032 			pid = fork();
1033 			if (pid == -1) {
1034 				res = -1;
1035 			} else if (pid == 0) {
1036 				/* son */
1037 				res = system(cmd);
1038 				res = WEXITSTATUS(res);
1039 				_exit(res);
1040 			} else {
1041 				int status = 0;
1042 				time_t start_wait = time(NULL);
1043 				res = -1;
1044 				do {
1045 					if (waitpid(pid, &status, WNOHANG) == 0 || !WIFEXITED(status)) {
1046 						usleep(200000);
1047 					} else {
1048 						res = WEXITSTATUS(status);
1049 						break;
1050 					}
1051 					if (time(NULL) - start_wait > 5) {
1052 						debug_print("SIGTERM'ing gpg\n");
1053 						kill(pid, SIGTERM);
1054 					}
1055 					if (time(NULL) - start_wait > 6) {
1056 						debug_print("SIGKILL'ing gpg\n");
1057 						kill(pid, SIGKILL);
1058 						break;
1059 					}
1060 				} while(1);
1061 			}
1062 
1063 			if (res == 0)
1064 				exported = TRUE;
1065 #else
1066 			/* We need to call gpg in a separate thread, so that waiting for
1067 			 * it to finish does not block the UI. */
1068 			pthread_t pt;
1069 			struct _ExportCtx *ectx = malloc(sizeof(struct _ExportCtx));
1070 
1071 			ectx->done = FALSE;
1072 			ectx->exitcode = STILL_ACTIVE;
1073 			ectx->cmd = cmd;
1074 
1075 			if (pthread_create(&pt, NULL,
1076 						_export_threaded, (void *)ectx) != 0) {
1077 				debug_print("Couldn't create thread, continuing unthreaded.\n");
1078 				_export_threaded(ctx);
1079 			} else {
1080 				debug_print("Thread created, waiting for it to finish...\n");
1081 				while (!ectx->done)
1082 					claws_do_idle();
1083 			}
1084 
1085 			debug_print("Thread finished.\n");
1086 			pthread_join(pt, NULL);
1087 
1088 			if (ectx->exitcode == 0)
1089 				exported = TRUE;
1090 
1091 			g_free(ectx);
1092 #endif
1093 			g_free(cmd);
1094 
1095 			if (exported) {
1096 				alertpanel_notice(_("Key exported."));
1097 			} else {
1098 				alertpanel_error(_("Couldn't export key."));
1099 			}
1100 		}
1101 	}
1102 	gpgme_release(ctx);
1103 }
1104 
sgpgme_has_secret_key(void)1105 gboolean sgpgme_has_secret_key(void)
1106 {
1107 	gpgme_error_t err = 0;
1108 	gpgme_ctx_t ctx;
1109 	gpgme_key_t key;
1110 
1111 	err = gpgme_new (&ctx);
1112 	if (err) {
1113 		debug_print("err : %s\n", gpgme_strerror(err));
1114 		return TRUE;
1115 	}
1116 check_again:
1117 	err = gpgme_op_keylist_start(ctx, NULL, TRUE);
1118 	if (!err) {
1119 		err = gpgme_op_keylist_next(ctx, &key);
1120 		gpgme_key_unref(key); /* We're not interested in the key itself. */
1121 	}
1122 	gpgme_op_keylist_end(ctx);
1123 	if (gpg_err_code(err) == GPG_ERR_EOF) {
1124 		if (gpgme_get_protocol(ctx) != GPGME_PROTOCOL_CMS) {
1125 			gpgme_set_protocol(ctx, GPGME_PROTOCOL_CMS);
1126 			goto check_again;
1127 		}
1128 		gpgme_release(ctx);
1129 		return FALSE;
1130 	} else {
1131 		gpgme_release(ctx);
1132 		return TRUE;
1133 	}
1134 }
1135 
sgpgme_check_create_key(void)1136 void sgpgme_check_create_key(void)
1137 {
1138 	if (prefs_gpg_get_config()->gpg_ask_create_key &&
1139 	    !sgpgme_has_secret_key()) {
1140 		sgpgme_create_secret_key(NULL, TRUE);
1141 	}
1142 
1143 	prefs_gpg_get_config()->gpg_ask_create_key = FALSE;
1144 	prefs_gpg_save_config();
1145 }
1146 
sgpgme_data_release_and_get_mem(gpgme_data_t data,size_t * len)1147 void *sgpgme_data_release_and_get_mem(gpgme_data_t data, size_t *len)
1148 {
1149 	char buf[BUFSIZ];
1150 	void *result = NULL;
1151 	ssize_t r = 0;
1152 	size_t w = 0;
1153 
1154 	cm_return_val_if_fail(data != NULL, NULL);
1155 	cm_return_val_if_fail(len != NULL, NULL);
1156 
1157 	/* I know it's deprecated, but we don't compile with _LARGEFILE */
1158 	cm_gpgme_data_rewind(data);
1159 	while ((r = gpgme_data_read(data, buf, BUFSIZ)) > 0) {
1160 		void *rresult = realloc(result, r + w);
1161 		if (rresult == NULL) {
1162 			g_warning("can't allocate memory");
1163 			if (result != NULL)
1164 				free(result);
1165 			return NULL;
1166 		}
1167 		result = rresult;
1168 		memcpy(result+w, buf, r);
1169 		w += r;
1170 	}
1171 
1172 	*len = w;
1173 
1174 	gpgme_data_release(data);
1175 	if (r < 0) {
1176 		g_warning("gpgme_data_read() returned an error: %d", (int)r);
1177 		free(result);
1178 		*len = 0;
1179 		return NULL;
1180 	}
1181 	return result;
1182 }
1183 
cm_gpgme_data_rewind(gpgme_data_t dh)1184 gpgme_error_t cm_gpgme_data_rewind(gpgme_data_t dh)
1185 {
1186 #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
1187 	if (gpgme_data_seek(dh, (off_t)0, SEEK_SET) == -1)
1188 		return gpg_error_from_errno(errno);
1189 	else
1190 		return 0;
1191 #else
1192 	return gpgme_data_rewind(dh);
1193 #endif
1194 }
1195 
1196 #endif /* USE_GPGME */
1197