Fix a few 'gcc -fanalyzer' warnings.
[pwmd.git] / src / crypto.c
blob8b549d7a752b891e7e056dddd18be3024e3e1e99
1 /*
2 Copyright (C) 2006-2023 Ben Kibbey <bjk@luxsci.net>
4 This file is part of pwmd.
6 Pwmd is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License version 2 as
8 published by the Free Software Foundation.
10 Pwmd 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 Pwmd. If not, see <http://www.gnu.org/licenses/>.
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
22 #include <stdio.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #ifdef HAVE_FCNTL_H
26 #include <fcntl.h>
27 #endif
28 #include <errno.h>
29 #include <pthread.h>
31 #ifdef WITH_LIBACL
32 #ifdef HAVE_SYS_ACL_H
33 #include <sys/acl.h>
34 #endif
35 #endif
37 #include "pwmd-error.h"
38 #include "util-misc.h"
39 #include "common.h"
40 #include "rcfile.h"
41 #include "crypto.h"
42 #include "cache.h"
43 #include "mem.h"
44 #include "util-string.h"
45 #include "rcfile.h"
46 #include "mutex.h"
48 static unsigned keepalive;
49 static pthread_mutex_t crypto_mutex = PTHREAD_MUTEX_INITIALIZER;
51 #define BUFSIZE 4096
53 #define STATUS_TIMEOUT_INIT(crypto) \
54 do { \
55 crypto->status_timeout = time (NULL); \
56 crypto->progress_rc = 0; \
57 } while (0)
59 #define STATUS_TIMEOUT_TEST(crypto, rc, s, line) \
60 do { \
61 time_t now = time (NULL); \
62 if (now - crypto->status_timeout >= keepalive && crypto->client_ctx) { \
63 rc = send_status (crypto->client_ctx, s, line); \
64 crypto->status_timeout = now; \
65 } \
66 } while (0)
68 static gpg_error_t
69 get_password_file (const char *keyfile, unsigned char **result, size_t *len)
71 struct stat st;
72 int fd;
73 unsigned char *buf = NULL;
74 gpg_error_t rc = 0;
76 log_write (_ ("obtaining passphrase from passphrase file"));
77 rc = open_check_file (keyfile, &fd, &st, 0);
78 if (rc)
79 return rc;
81 buf = xmalloc (st.st_size+1);
82 if (buf)
84 size_t rlen = read (fd, buf, st.st_size);
86 if (rlen != st.st_size)
87 rc = GPG_ERR_ASS_READ_ERROR;
88 else
90 buf[rlen] = 0;
91 /* The passphrase may have been truncated do to a nul byte before the
92 * EOF. Better to return an error here rather than passing the
93 * truncated passphrase on. */
94 if (rlen && strlen ((char *)buf) != rlen)
95 rc = GPG_ERR_INV_PASSPHRASE;
97 if (!rc)
99 *result = buf;
100 *len = rlen;
104 else
105 rc = GPG_ERR_ENOMEM;
107 close (fd);
108 if (rc)
109 xfree (buf);
111 return rc;
114 static gpgme_error_t
115 status_cb (void *data, const char *keyword, const char *args)
117 struct crypto_s *crypto = data;
119 // Cache pushing.
120 if (!crypto->client_ctx)
121 return 0;
123 if (!strcmp (keyword, "INQUIRE_MAXLEN") &&
124 (crypto->flags & CRYPTO_FLAG_KEYFILE))
125 return 0;
127 return assuan_write_status (crypto->client_ctx, keyword, args);
130 static gpgme_error_t
131 passphrase_cb (void *data, const char *hint, const char *info, int bad, int fd)
133 struct crypto_s *crypto = data;
134 unsigned char *result = NULL;
135 size_t len;
136 gpg_error_t rc = 0;
138 if (crypto->flags & CRYPTO_FLAG_KEYFILE)
139 rc = get_password_file (crypto->keyfile, &result, &len);
140 else
142 if (hint)
143 rc = assuan_write_status (crypto->client_ctx, "PASSPHRASE_HINT", hint);
145 if (!rc && info)
146 rc = assuan_write_status (crypto->client_ctx, "PASSPHRASE_INFO", info);
148 if (!rc)
150 const char *keyword = "PASSPHRASE";
152 if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD_SIGN)
153 keyword = "SIGN_PASSPHRASE";
154 else if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD_NEW)
156 crypto->flags |= CRYPTO_FLAG_PASSWD_SIGN;
157 keyword = "NEW_PASSPHRASE";
159 else if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD)
160 crypto->flags |= CRYPTO_FLAG_PASSWD_NEW;
161 else if (!bad && crypto->flags & CRYPTO_FLAG_NEWFILE)
163 keyword = "NEW_PASSPHRASE";
164 if (crypto->save.sigkey)
165 crypto->flags |= CRYPTO_FLAG_PASSWD_SIGN;
168 rc = assuan_inquire (crypto->client_ctx, keyword, &result, &len, 0);
172 if (!rc)
174 pthread_cleanup_push ((void *)xfree, result);
176 if (!len)
177 gpgme_io_writen (fd, "\n", 1);
178 else
180 int nl = result[len-1] == '\n';
181 int ret;
183 ret = gpgme_io_writen (fd, result, len);
184 if (!ret && !nl)
185 gpgme_io_writen (fd, "\n", 1);
186 else if (ret)
187 rc = GPG_ERR_CANCELED;
190 pthread_cleanup_pop (1);
193 return rc;
196 static void
197 progress_cb (void *data, const char *what, int type, int current, int total)
199 struct crypto_s *crypto = data;
201 crypto->progress_rc = send_status (crypto->client_ctx, STATUS_GPGME,
202 "%s %i %i %i", what, type, current, total);
205 gpgme_error_t
206 crypto_data_to_buf (const gpgme_data_t data, unsigned char **result,
207 size_t *rlen)
209 off_t ret = gpgme_data_seek (data, 0, SEEK_SET);
210 gpgme_error_t rc;
211 size_t total = 0, size = BUFSIZE;
212 unsigned char *buf = NULL;
214 *result = NULL;
215 *rlen = 0;
217 if (ret == -1)
218 return gpg_error_from_syserror ();
220 buf = xmalloc (size);
221 if (!buf)
222 return GPG_ERR_ENOMEM;
226 ret = gpgme_data_read (data, &buf[total], BUFSIZE);
227 if (ret > 0)
229 unsigned char *p;
231 total += ret;
232 size += BUFSIZE;
233 p = xrealloc (buf, size * sizeof (unsigned char));
234 if (!p)
236 xfree (buf);
237 return GPG_ERR_ENOMEM;
240 buf = p;
242 } while (ret > 0);
244 if (ret == -1)
246 rc = gpgme_err_code_from_syserror ();
247 xfree (buf);
248 return rc;
251 if (!total)
252 xfree (buf);
253 else
254 *result = buf;
256 *rlen = total;
257 return 0;
260 gpgme_error_t
261 crypto_list_keys (struct crypto_s *crypto, char *keys[], int secret,
262 gpgme_key_t **result)
264 gpgme_error_t rc;
265 gpgme_key_t key = NULL, *res = NULL;
266 size_t total = 0;
268 rc = gpgme_op_keylist_ext_start (crypto->ctx, (const char **)keys, secret, 0);
269 if (rc)
270 return rc;
272 STATUS_TIMEOUT_INIT (crypto);
275 gpgme_key_t *p;
277 pthread_cleanup_push ((void *)crypto_free_key_list, res);
278 rc = gpgme_op_keylist_next (crypto->ctx, &key);
279 pthread_cleanup_pop (0);
280 if (rc && gpgme_err_code(rc) != GPG_ERR_EOF)
281 break;
283 if (rc)
285 rc = 0;
286 break;
289 p = xrealloc (res, (total+2) * sizeof (gpgme_key_t));
290 if (!p)
292 rc = GPG_ERR_ENOMEM;
293 break;
296 res = p;
297 res[total++] = key;
298 res[total] = NULL;
299 pthread_cleanup_push ((void *)crypto_free_key_list, res);
300 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_KEEPALIVE, NULL);
301 pthread_cleanup_pop (0);
302 } while (!rc);
304 if (!rc)
306 rc = gpgme_op_keylist_end (crypto->ctx);
307 if (!rc)
309 *result = res;
310 rc = total ? 0 : secret ? GPG_ERR_NO_SECKEY : GPG_ERR_NO_PUBKEY;
313 else
314 crypto_free_key_list (res);
316 return rc;
319 void
320 crypto_free_save (struct save_s *save)
322 if (!save)
323 return;
325 strv_free (save->pubkey);
326 xfree (save->sigkey);
327 xfree (save->userid);
328 xfree (save->algo);
329 crypto_free_key_list (save->mainkey);
331 memset (save, 0, sizeof (struct save_s));
334 static void
335 free_gpgme_data_cb (void *data)
337 gpgme_data_t d = data;
338 char *t;
339 size_t len;
341 if (!data)
342 return;
344 t = gpgme_data_release_and_get_mem (d, &len);
345 if (t)
346 wipememory (t, 0, len);
348 gpgme_free (t);
351 void
352 crypto_free_non_keys (struct crypto_s *crypto)
354 if (!crypto)
355 return;
357 if (crypto->ctx)
358 gpgme_release (crypto->ctx);
360 crypto->ctx = NULL;
361 xfree (crypto->plaintext);
362 crypto->plaintext = NULL;
363 crypto->plaintext_size = 0;
365 if (crypto->cipher)
366 free_gpgme_data_cb (crypto->cipher);
368 crypto->cipher = NULL;
369 crypto_free_save (&crypto->save);
370 xfree (crypto->keyfile);
371 crypto->keyfile = NULL;
372 crypto->flags &= ~CRYPTO_FLAG_KEYFILE;
375 void
376 crypto_free (struct crypto_s *crypto)
378 if (!crypto)
379 return;
381 crypto_free_non_keys (crypto);
382 strv_free (crypto->pubkey);
383 xfree (crypto->sigkey);
384 xfree (crypto->filename);
385 xfree (crypto);
388 gpgme_error_t
389 crypto_init_ctx (struct crypto_s *crypto, int no_pinentry,
390 char *passphrase_file)
392 gpgme_ctx_t ctx;
393 gpgme_keylist_mode_t keylist_mode;
394 gpgme_error_t rc;
396 rc = gpgme_new (&ctx);
397 if (rc)
398 return rc;
400 rc = gpgme_set_protocol (ctx, GPGME_PROTOCOL_OPENPGP);
401 if (!rc)
403 keylist_mode = gpgme_get_keylist_mode (ctx);
404 keylist_mode |= GPGME_KEYLIST_MODE_LOCAL|GPGME_KEYLIST_MODE_WITH_SECRET;
405 rc = gpgme_set_keylist_mode (ctx, keylist_mode);
406 if (!rc)
408 if (no_pinentry || passphrase_file)
409 rc = gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_LOOPBACK);
410 else
411 rc = gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_DEFAULT);
413 if (!rc)
415 gpgme_set_ctx_flag (ctx, "no-symkey-cache", "1");
416 gpgme_set_passphrase_cb (ctx, passphrase_cb, crypto);
417 gpgme_set_progress_cb (ctx, progress_cb, crypto);
418 gpgme_set_status_cb (ctx, status_cb, crypto);
419 crypto->ctx = ctx;
420 crypto->flags = 0;
422 if (passphrase_file)
424 crypto->keyfile = passphrase_file;
425 crypto->flags |= CRYPTO_FLAG_KEYFILE;
431 if (rc)
432 gpgme_release (ctx);
434 return rc;
437 void
438 crypto_set_keepalive ()
440 keepalive = config_get_integer ("global", "keepalive_interval");
443 gpg_error_t
444 crypto_init (struct crypto_s **crypto, void *ctx, const char *filename,
445 int no_pinentry, char *passphrase_file)
447 struct crypto_s *new = xcalloc (1, sizeof (struct crypto_s));
448 gpgme_error_t rc;
450 crypto_set_keepalive ();
452 if (!new)
453 return GPG_ERR_ENOMEM;
455 rc = crypto_init_ctx (new, no_pinentry, passphrase_file);
456 if (rc)
457 goto fail;
459 if (filename)
461 new->filename = str_dup (filename);
462 if (!new->filename)
464 rc = GPG_ERR_ENOMEM;
465 goto fail;
469 new->client_ctx = ctx;
470 *crypto = new;
471 return 0;
473 fail:
474 crypto_free (new);
475 return rc;
478 /* Converts a 40 byte key id to the 16 byte form. Needed for comparison of
479 * gpgme_recipient_t.keyid. */
480 gpg_error_t
481 crypto_keyid_to_16b_once (char *key)
483 size_t len = strlen (key);
485 if (len < 16)
486 return GPG_ERR_INV_ARG;
488 memmove (&key[0], &key[len-16], 16);
489 key[16] = 0;
490 return 0;
493 gpg_error_t
494 crypto_keyid_to_16b (char **keys)
496 char **p;
498 for (p = keys; p && *p; p++)
500 gpg_error_t rc = crypto_keyid_to_16b_once (*p);
501 if (rc)
502 return rc;
505 return 0;
508 gpgme_error_t
509 crypto_decrypt (struct client_s *client, struct crypto_s *crypto)
511 gpgme_data_t plain;
512 gpgme_error_t rc;
513 gpgme_data_t cipher;
514 int fd = -1;
515 struct stat st;
516 char **new_recipients = NULL;
517 char **new_signers = NULL;
518 char **pp;
519 gpgme_decrypt_result_t result;
521 rc = gpgme_data_new (&plain);
522 if (rc)
523 return rc;
525 if (gpgme_check_version ("1.16.0"))
527 gpgme_data_set_flag (plain, "io-buffer-size", "4096");
528 gpgme_data_set_flag (plain, "sensitive", "1");
531 pthread_cleanup_push ((void *)free_gpgme_data_cb, plain);
532 rc = open_check_file (crypto->filename, &fd, &st, 1);
533 if (!rc)
535 pthread_cleanup_push ((void *)close_fd_cb, &fd);
536 rc = gpgme_data_new_from_fd (&cipher, fd);
537 if (!rc)
539 pthread_cleanup_push ((void *)free_gpgme_data_cb, cipher);
540 rc = send_status (client ? client->ctx : NULL, STATUS_DECRYPT, NULL);
541 if (!rc)
543 MUTEX_TRYLOCK ((client ? client->ctx : NULL), &crypto_mutex, rc,
544 (client ? client->lock_timeout : -1));
545 if (!rc)
547 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
548 rc = gpgme_op_decrypt_verify_start (crypto->ctx, cipher, plain);
549 if (!rc)
551 STATUS_TIMEOUT_INIT(crypto);
554 if (!rc && crypto->progress_rc)
555 rc = crypto->progress_rc;
556 if (!rc)
557 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_DECRYPT, NULL);
558 TEST_CANCEL ();
559 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
561 pthread_cleanup_pop (1); // release_mutex_cb
564 pthread_cleanup_pop (1); // free_gpgme_data_cb (cipher)
567 pthread_cleanup_pop (1); // close (fd)
570 pthread_cleanup_pop (0); // free_gpgme_data_cb (plain)
572 if (rc)
574 free_gpgme_data_cb (plain);
575 return rc;
578 pthread_cleanup_push ((void *)free_gpgme_data_cb, plain);
579 result = gpgme_op_decrypt_result (crypto->ctx);
580 if (!result->unsupported_algorithm && !result->wrong_key_usage)
582 gpgme_recipient_t r;
584 for (r = result->recipients; r; r = r->next)
586 pthread_cleanup_push ((void *)strv_free, new_recipients);
587 log_write1 (_ ("%s: recipient: %s, status=%u"),
588 crypto->filename, r->keyid, r->status);
589 pthread_cleanup_pop (0);
590 pp = strv_cat(new_recipients, str_dup (r->keyid));
591 if (!pp)
593 rc = GPG_ERR_ENOMEM;
594 break;
597 new_recipients = pp;
600 else if (result->wrong_key_usage)
601 rc = GPG_ERR_WRONG_KEY_USAGE;
602 else if (result->unsupported_algorithm)
603 rc = GPG_ERR_UNSUPPORTED_ALGORITHM;
605 if (!rc)
607 gpgme_verify_result_t verify;
608 gpgme_signature_t s;
610 verify = gpgme_op_verify_result (crypto->ctx);
611 for (s = verify->signatures; s; s = s->next)
613 unsigned flags = s->summary;
615 pthread_cleanup_push ((void *)strv_free, new_signers);
616 log_write1 (_ ("%s: signer: %s, status=%u"),
617 crypto->filename, s->fpr, s->status);
618 pthread_cleanup_pop (0);
620 flags &= ~(GPGME_SIGSUM_KEY_EXPIRED|GPGME_SIGSUM_SIG_EXPIRED);
621 if (!flags)
622 flags |= GPGME_SIGSUM_VALID;
624 if (gpg_err_code (s->status) == GPG_ERR_KEY_EXPIRED)
625 s->status = 0;
627 if (s->status || s->wrong_key_usage || !(flags & GPGME_SIGSUM_VALID))
628 continue;
630 pp = strv_cat (new_signers, str_dup (s->fpr));
631 if (!pp)
633 rc = GPG_ERR_ENOMEM;
634 break;
637 new_signers = pp;
640 if (verify->signatures && !new_signers)
641 rc = GPG_ERR_BAD_SIGNATURE;
643 if (!rc)
645 xfree (crypto->plaintext);
646 crypto->plaintext = NULL;
647 crypto->plaintext_size = 0;
648 pthread_cleanup_push ((void *)strv_free, new_recipients);
649 pthread_cleanup_push ((void *)strv_free, new_signers);
650 rc = crypto_data_to_buf (plain, &crypto->plaintext,
651 &crypto->plaintext_size);
652 pthread_cleanup_pop (0);
653 pthread_cleanup_pop (0);
654 if (!rc)
656 strv_free (crypto->pubkey);
657 crypto->pubkey = new_recipients;
658 crypto_keyid_to_16b (crypto->pubkey);
660 xfree (crypto->sigkey);
661 crypto->sigkey = NULL;
662 if (new_signers)
664 crypto->sigkey = str_dup (*new_signers);
665 strv_free (new_signers);
666 crypto_keyid_to_16b_once (crypto->sigkey);
672 if (rc)
674 strv_free (new_recipients);
675 strv_free (new_signers);
678 pthread_cleanup_pop (1); // free_gpgme_data_cb (plain)
679 return rc;
682 void
683 crypto_free_key_list (gpgme_key_t *keys)
685 int i;
687 for (i = 0; keys && keys[i]; i++)
688 gpgme_key_unref (keys[i]);
690 xfree (keys);
693 /* Removes strings in 'prune' from 'a'. */
694 static char **
695 prune_keys (char **a, char **prune)
697 char **p;
699 for (p = prune; p && *p; p++)
701 char **ap;
703 for (ap = a; ap && *ap; ap++)
705 if (!strcmp (*ap, *p))
707 while (*ap)
709 *ap = *(ap+1);
710 ap++;
716 return a;
719 static void
720 remove_duplicates (char **a)
722 char **p;
724 for (p = a; p && *p; p++)
726 char **t;
728 for (t = p+1; t && *t; t++)
730 if (!strcmp (*p, *t))
732 char *tmp = *t;
734 while (*(t+1))
736 *t = *(t+1);
737 t++;
740 *t = NULL;
741 xfree (tmp);
742 remove_duplicates (a);
743 return;
749 gpgme_error_t
750 crypto_encrypt (struct client_s *client, struct crypto_s *crypto)
752 gpgme_error_t rc;
753 gpgme_data_t cipher = NULL;
754 gpgme_key_t *keys = NULL;
755 gpgme_key_t *sigkeys = NULL;
756 unsigned flags = 0;
757 int sign = 0;
759 if (!((crypto->flags & CRYPTO_FLAG_SYMMETRIC)))
761 crypto_keyid_to_16b (crypto->save.pubkey);
762 remove_duplicates (crypto->save.pubkey);
763 rc = crypto_list_keys (crypto, crypto->save.pubkey, 0, &keys);
764 if (rc)
765 return rc;
768 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
769 rc = gpgme_data_new (&cipher);
770 pthread_cleanup_push ((void *)free_gpgme_data_cb, cipher);
771 if (!rc)
772 rc = gpgme_data_set_file_name (cipher, crypto->filename);
774 if (!rc && crypto->save.sigkey)
776 char **tmp = NULL;
778 crypto_keyid_to_16b_once (crypto->save.sigkey);
779 strv_printf (&tmp, "%s", crypto->save.sigkey);
780 pthread_cleanup_push ((void *)strv_free, tmp);
781 rc = crypto_list_keys (crypto, tmp, 1, &sigkeys);
782 pthread_cleanup_pop (1);
783 if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
784 rc = 0;
787 if (!rc)
789 gpgme_data_t plain = NULL;
791 pthread_cleanup_push ((void *)crypto_free_key_list, sigkeys);
792 rc = gpgme_data_new_from_mem (&plain, (char *)crypto->plaintext,
793 crypto->plaintext_size, 0);
794 pthread_cleanup_push ((void *)free_gpgme_data_cb, plain);
795 if (!rc)
797 int i;
799 gpgme_signers_clear (crypto->ctx);
801 for (i = 0; sigkeys && sigkeys[i]; i++)
802 gpgme_signers_add (crypto->ctx, sigkeys[i]);
805 if (!rc)
807 gpgme_data_set_encoding (cipher, GPGME_DATA_ENCODING_ARMOR);
808 rc = send_status (client ? client->ctx : NULL, STATUS_ENCRYPT, NULL);
811 if (!rc)
813 int f = config_get_boolean ("global", "encrypt_to");
815 if (!f)
816 flags |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
818 f = config_get_boolean ("global", "always_trust");
819 if (f)
820 flags |= GPGME_ENCRYPT_ALWAYS_TRUST;
822 if (!(crypto->flags & CRYPTO_FLAG_SYMMETRIC)
823 || (crypto->flags & CRYPTO_FLAG_SYMMETRIC && sigkeys))
824 sign = 1;
827 if (!rc)
828 MUTEX_TRYLOCK ((client ? client->ctx : NULL), &crypto_mutex, rc,
829 (client ? client->lock_timeout : -1));
831 if (!rc)
833 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
834 if (sign)
835 rc = gpgme_op_encrypt_sign_start (crypto->ctx, keys, flags, plain,
836 cipher);
837 else
838 rc = gpgme_op_encrypt_start (crypto->ctx, NULL, flags, plain,
839 cipher);
840 if (!rc)
842 STATUS_TIMEOUT_INIT (crypto);
845 if (!rc && crypto->progress_rc)
846 rc = crypto->progress_rc;
847 if (!rc)
848 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_ENCRYPT, NULL);
849 TEST_CANCEL();
850 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
852 pthread_cleanup_pop (1);
854 if (!rc)
856 gpgme_encrypt_result_t result;
857 gpgme_sign_result_t sresult;
858 gpgme_invalid_key_t inv;
859 gpgme_new_signature_t sigs;
860 char **prune = NULL;
861 char **p = NULL;
863 result = gpgme_op_encrypt_result (crypto->ctx);
864 inv = result->invalid_recipients;
865 while (inv)
867 pthread_cleanup_push ((void *)strv_free, prune);
868 log_write1 (_ ("%s: invalid recipient: %s, rc=%u"),
869 crypto->filename, inv->fpr, inv->reason);
870 pthread_cleanup_pop (0);
871 p = strv_cat (prune, str_dup(inv->fpr));
872 if (!p)
874 rc = GPG_ERR_ENOMEM;
875 strv_free (prune);
876 break;
879 prune = p;
880 inv = inv->next;
883 if (prune)
885 p = prune_keys (crypto->save.pubkey, prune);
886 crypto->save.pubkey = p;
887 strv_free (prune);
890 crypto_keyid_to_16b (crypto->save.pubkey);
891 sresult = gpgme_op_sign_result (crypto->ctx);
892 inv = sresult ? sresult->invalid_signers : NULL;
893 while (!rc && inv)
895 log_write1 (_ ("%s: invalid signer: %s, rc=%u"),
896 crypto->filename, inv->fpr, inv->reason);
897 inv = inv->next;
900 sigs = sresult ? sresult->signatures : NULL;
901 if (!rc && sigs)
903 p = NULL;
905 while (sigs)
907 char **pp;
909 pthread_cleanup_push ((void *)strv_free, p);
910 log_write1 (_ ("%s: signer: %s"), crypto->filename,
911 sigs->fpr);
912 pthread_cleanup_pop (0);
914 pp = strv_cat (p, str_dup (sigs->fpr));
915 if (!pp)
917 rc = GPG_ERR_ENOMEM;
918 strv_free (p);
919 break;
922 p = pp;
923 sigs = sigs->next;
926 if (!rc)
928 xfree (crypto->save.sigkey);
929 crypto->save.sigkey = str_dup (*p);
930 strv_free (p);
931 crypto_keyid_to_16b_once (crypto->save.sigkey);
932 crypto->cipher = cipher;
935 else if (!rc && crypto->flags & CRYPTO_FLAG_SYMMETRIC)
937 crypto->cipher = cipher;
939 else if (!rc)
941 if (!(crypto->flags & CRYPTO_FLAG_SYMMETRIC)
942 || (crypto->flags & CRYPTO_FLAG_SYMMETRIC && sigkeys))
943 rc = GPG_ERR_NO_SIGNATURE_SCHEME;
948 pthread_cleanup_pop (1); // free_gpgme_data_cb (plain)
949 pthread_cleanup_pop (1); // crypto_free_key_list (sigkeys)
952 pthread_cleanup_pop (0); // free_gpgme_data_cb (cipher)
953 pthread_cleanup_pop (1); // crypto_free_key_list (keys)
955 if (rc)
956 free_gpgme_data_cb (cipher);
958 return rc;
961 gpgme_error_t
962 crypto_passwd (struct client_s *client, struct crypto_s *crypto)
964 gpgme_error_t rc;
965 gpgme_key_t *keys = NULL;
967 /* Use SAVE instead for symmetric files. */
968 rc = crypto_is_symmetric (client->filename);
969 if (!rc || rc != GPG_ERR_BAD_DATA)
970 return !rc ? GPG_ERR_NOT_SUPPORTED : rc;
972 /* Cannot change the passphrase of a key stored on a smartcard. Use
973 * gpg --card-edit instead. */
974 rc = cache_is_shadowed (client->filename);
975 if (!rc)
976 return GPG_ERR_NOT_SUPPORTED;
977 else if (rc != GPG_ERR_NO_DATA)
978 return rc;
980 rc = crypto_list_keys (crypto, crypto->pubkey, 1, &keys);
981 if (rc)
982 return rc;
984 crypto->flags |= CRYPTO_FLAG_PASSWD;
985 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
986 rc = send_status (client->ctx, STATUS_KEEPALIVE, NULL);
987 if (!rc)
988 MUTEX_TRYLOCK (client->ctx, &crypto_mutex, rc, client->lock_timeout);
990 if (!rc)
992 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
993 rc = gpgme_op_passwd_start (crypto->ctx, keys[0], 0);
994 if (!rc)
996 STATUS_TIMEOUT_INIT (crypto);
999 if (!rc && crypto->progress_rc)
1000 rc = crypto->progress_rc;
1001 if (!rc)
1002 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_KEEPALIVE, NULL);
1003 TEST_CANCEL();
1004 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
1006 pthread_cleanup_pop (1);
1009 pthread_cleanup_pop (1);
1010 return rc;
1013 /* Generate a new key pair. The resulting keyid's are stored in crypto->save.
1015 gpgme_error_t
1016 crypto_genkey (struct client_s *client, struct crypto_s *crypto)
1018 gpgme_error_t rc;
1020 rc = send_status (client ? client->ctx : NULL, STATUS_GENKEY, NULL);
1021 if (!rc)
1022 MUTEX_TRYLOCK ((client ? client->ctx : NULL), &crypto_mutex, rc,
1023 (client ? client->lock_timeout : 0));
1025 if (!rc)
1027 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
1028 if (crypto->save.mainkey)
1030 rc = gpgme_op_createsubkey_start (crypto->ctx,
1031 crypto->save.mainkey[0],
1032 crypto->save.algo,
1034 crypto->save.expire,
1035 crypto->save.flags);
1037 else
1039 rc = gpgme_op_createkey_start (crypto->ctx,
1040 crypto->save.userid,
1041 crypto->save.algo,
1043 crypto->save.expire,
1044 NULL,
1045 crypto->save.flags);
1048 if (!rc)
1050 STATUS_TIMEOUT_INIT (crypto);
1053 if (!rc && crypto->progress_rc)
1054 rc = crypto->progress_rc;
1055 if (!rc)
1056 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_GENKEY, NULL);
1057 TEST_CANCEL();
1058 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
1060 pthread_cleanup_pop (1);
1063 if (!rc)
1065 gpgme_key_t *keys = NULL;
1066 gpgme_genkey_result_t result;
1068 result = gpgme_op_genkey_result (crypto->ctx);
1069 xfree (crypto->save.sigkey);
1070 crypto->save.sigkey = str_dup (result->fpr);
1071 crypto_keyid_to_16b_once (crypto->save.sigkey);
1073 if (!rc)
1075 char **tmp = NULL;
1077 strv_printf (&tmp, "%s", crypto->save.sigkey);
1078 pthread_cleanup_push ((void *)strv_free, tmp);
1079 rc = crypto_list_keys (crypto, tmp, 1, &keys);
1080 pthread_cleanup_pop (1);
1083 if (!rc)
1085 gpgme_subkey_t key = keys[0]->subkeys;
1087 for (; key; key = key->next)
1089 if (key->can_encrypt)
1090 break;
1093 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
1094 rc = send_status (client ? client->ctx : NULL, STATUS_GENKEY, "%s %s",
1095 crypto->save.sigkey, key ? key->fpr : "");
1096 if (!rc && key)
1098 crypto->save.pubkey = strv_cat (crypto->save.pubkey,
1099 str_dup (key->fpr));
1100 crypto_keyid_to_16b (crypto->save.pubkey);
1103 pthread_cleanup_pop (1);
1107 return rc;
1110 #ifdef WITH_LIBACL
1111 static void
1112 acl_free_cb (void *arg)
1114 acl_t acl = arg ? (acl_t) arg : NULL;
1116 if (acl)
1117 acl_free (acl);
1119 #endif
1121 /* The advisory lock should be obtained before calling this function. */
1122 gpg_error_t
1123 crypto_write_file (struct crypto_s *crypto, unsigned char **r_crc,
1124 size_t *r_crclen)
1126 unsigned char *buf;
1127 size_t size, len;
1128 int fd;
1129 gpg_error_t rc;
1130 char tmp[PATH_MAX];
1131 struct stat st;
1132 mode_t mode = 0600;
1133 #ifdef WITH_LIBACL
1134 acl_t acl = NULL;
1135 #endif
1137 if (crypto->filename)
1139 if (lstat (crypto->filename, &st) == 0)
1141 mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
1143 if (!(mode & S_IWUSR))
1144 return GPG_ERR_EACCES;
1146 else if (errno != ENOENT)
1147 return gpg_error_from_errno (errno);
1149 snprintf (tmp, sizeof (tmp), "%s.XXXXXX", crypto->filename);
1150 mode_t tmode = umask (0600);
1151 fd = mkstemp (tmp);
1152 if (fd == -1)
1154 rc = gpg_error_from_errno (errno);
1155 umask (tmode);
1156 log_write ("%s: %s", tmp, pwmd_strerror (rc));
1157 return rc;
1160 umask (tmode);
1162 else
1163 fd = STDOUT_FILENO;
1165 rc = crypto_data_to_buf (crypto->cipher, &buf, &size);
1166 if (rc)
1168 if (crypto->filename)
1169 close (fd);
1170 return rc;
1173 pthread_cleanup_push ((void *)close_fd_cb, &fd);
1174 if (r_crc)
1175 rc = get_checksum_memory (buf, size, r_crc, r_crclen);
1177 if (!rc)
1179 pthread_cleanup_push ((void *)xfree, buf);
1180 len = write (fd, buf, size);
1181 pthread_cleanup_pop (1);
1182 if (len != size)
1183 rc = gpg_error_from_errno (errno);
1186 if (!rc)
1188 if (fsync (fd) != -1)
1190 if (crypto->filename && close (fd) != -1)
1192 #ifdef WITH_LIBACL
1193 acl = acl_get_file (crypto->filename, ACL_TYPE_ACCESS);
1194 if (!acl && errno == ENOENT)
1195 acl = acl_get_file (".", ACL_TYPE_DEFAULT);
1196 if (!acl)
1197 log_write ("ACL: %s: %s", crypto->filename,
1198 pwmd_strerror (gpg_error_from_errno (errno)));
1199 pthread_cleanup_push ((void *)acl_free_cb, acl);
1200 #endif
1202 fd = -1;
1203 if (config_get_boolean (crypto->filename, "backup"))
1205 char tmp2[PATH_MAX];
1207 snprintf (tmp2, sizeof (tmp2), "%s.backup", crypto->filename);
1208 if (rename (crypto->filename, tmp2) == -1)
1209 if (errno != ENOENT)
1210 rc = gpg_error_from_errno (errno);
1213 if (!rc && rename (tmp, crypto->filename) == -1)
1214 rc = gpg_error_from_errno (errno);
1216 if (!rc)
1218 if (chmod (crypto->filename, mode) == -1)
1219 log_write ("%s(%u): %s", __FILE__, __LINE__,
1220 pwmd_strerror (gpg_error_from_syserror ()));
1222 #ifdef WITH_LIBACL
1223 if (!rc && acl && acl_set_file (crypto->filename,
1224 ACL_TYPE_ACCESS, acl))
1225 log_write ("ACL: %s: %s", crypto->filename,
1226 pwmd_strerror (gpg_error_from_errno (errno)));
1227 pthread_cleanup_pop (1);
1228 #endif
1230 else if (crypto->filename)
1231 rc = gpg_error_from_errno (errno);
1233 if (!rc && fd != -1)
1235 char *datadir = str_asprintf ("%s/data", homedir);
1237 if (datadir)
1239 int dfd = open (datadir, O_RDONLY);
1241 if (dfd != -1)
1243 if (fsync (dfd) == -1)
1244 log_write ("%s %d: %s", __FILE__, __LINE__,
1245 pwmd_strerror (errno));
1247 close (dfd);
1249 else
1250 log_write ("%s %d: %s", __FILE__, __LINE__,
1251 pwmd_strerror (errno));
1253 xfree (datadir);
1257 else
1258 rc = gpg_error_from_errno (errno);
1261 pthread_cleanup_pop (0); // close (fd)
1262 if (fd != -1)
1263 close (fd);
1265 return rc;
1268 char *
1269 crypto_key_info (const gpgme_key_t key)
1271 struct string_s *string = string_new (NULL), *s;
1272 char *line = NULL;
1273 unsigned n, u;
1274 gpgme_subkey_t subkey;
1275 gpgme_user_id_t uid;
1277 if (!string)
1278 return NULL;
1280 for (u = 0, uid = key->uids; uid; uid = uid->next)
1281 u++;
1283 for (n = 0, subkey = key->subkeys; subkey; subkey = subkey->next)
1284 n++;
1286 s = string_append_printf (string, "%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%i:%s:%s:%s:%i:%u:%u",
1287 key->revoked, key->expired, key->disabled,
1288 key->invalid, key->can_encrypt, key->can_sign,
1289 key->can_certify, key->secret,
1290 key->can_authenticate, key->is_qualified,
1291 key->protocol,
1292 key->issuer_serial ? key->issuer_serial : "",
1293 key->issuer_name ? key->issuer_name : "",
1294 key->chain_id ? key->chain_id : "",
1295 key->owner_trust, u, n);
1296 if (!s)
1298 string_free (string, 1);
1299 return NULL;
1302 string = s;
1303 for (subkey = key->subkeys; subkey; subkey = subkey->next)
1305 char *tmp;
1307 s = string_append_printf (string, ":%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%i:%u",
1308 subkey->revoked, subkey->expired,
1309 subkey->disabled, subkey->invalid,
1310 subkey->can_encrypt, subkey->can_sign,
1311 subkey->can_certify, subkey->secret,
1312 subkey->can_authenticate, subkey->is_qualified,
1313 subkey->is_cardkey, subkey->pubkey_algo,
1314 subkey->length);
1315 if (!s)
1317 string_free (string, 1);
1318 return NULL;
1321 string = s;
1322 s = string_append_printf (string, ":%s:%s:%s:%li:%li:%s",
1323 subkey->keyid, subkey->fpr,
1324 subkey->keygrip ? subkey->keygrip : "",
1325 subkey->timestamp, subkey->expires,
1326 subkey->card_number ? subkey->card_number : "0");
1327 if (!s)
1329 string_free (string, 1);
1330 return NULL;
1333 string = s;
1334 tmp = gnupg_escape (subkey->curve);
1335 s = string_append_printf (string, ":%s", tmp ? tmp : "");
1336 xfree (tmp);
1337 if (!s)
1339 string_free (string, 1);
1340 return NULL;
1343 string = s;
1346 for (uid = key->uids; uid; uid = uid->next)
1348 char *userid, *name, *email, *comment;
1350 userid = gnupg_escape (uid->uid);
1351 name = gnupg_escape (uid->name);
1352 email = gnupg_escape (uid->email);
1353 comment = gnupg_escape (uid->comment);
1354 s = string_append_printf (string, ":%u:%u:%u:%s:%s:%s:%s",
1355 uid->revoked, uid->invalid, uid->validity,
1356 userid ? userid : "",
1357 name ? name : "",
1358 email ? email : "",
1359 comment ? comment : "");
1360 xfree (userid);
1361 xfree (name);
1362 xfree (email);
1363 xfree (comment);
1364 if (!s)
1366 string_free (string, 1);
1367 return NULL;
1370 string = s;
1373 line = string->str;
1374 string_free (string, 0);
1375 return line;
1378 gpg_error_t
1379 crypto_try_decrypt (struct client_s *client, int no_pinentry)
1381 struct crypto_s *crypto;
1382 gpg_error_t rc;
1383 char *keyfile = config_get_string (client->filename, "passphrase_file");
1385 rc = crypto_init (&crypto, client->ctx, client->filename, no_pinentry,
1386 keyfile);
1387 if (!rc)
1389 pthread_cleanup_push ((void *)crypto_free, crypto);
1390 rc = crypto_decrypt (client, crypto);
1391 pthread_cleanup_pop (1);
1393 else
1394 xfree (keyfile);
1396 return rc;
1399 /* The advisory lock should be obtained before calling this function. */
1400 gpg_error_t
1401 crypto_is_symmetric (const char *filename)
1403 int fd;
1404 uint8_t magic[2];
1405 ssize_t len;
1406 gpg_error_t rc;
1408 rc = open_check_file (filename, &fd, NULL, 1);
1409 if (rc)
1410 return rc;
1412 len = read (fd, &magic, sizeof(magic));
1413 close (fd);
1414 if (len != sizeof (magic))
1415 return GPG_ERR_INV_VALUE;
1417 // Always read as big endian.
1418 if (magic[0] != 0x8c || magic[1] != 0x0d)
1419 return GPG_ERR_BAD_DATA;
1421 return 0;
1424 gpg_error_t
1425 crypto_delete_key (struct client_s *client, struct crypto_s *crypto,
1426 const gpgme_key_t key, int secret)
1428 gpg_error_t rc;
1430 STATUS_TIMEOUT_INIT (crypto);
1431 rc = gpgme_op_delete_ext_start (crypto->ctx, key, GPGME_DELETE_FORCE
1432 | GPGME_DELETE_ALLOW_SECRET);
1433 if (rc)
1434 return rc;
1438 if (!rc && crypto->progress_rc)
1439 rc = crypto->progress_rc;
1441 if (!rc)
1442 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_KEEPALIVE, NULL);
1444 if (rc)
1445 break;
1446 } while (!gpgme_wait (crypto->ctx, &rc, 0) && !rc);
1448 return rc;