docs: Fix html menus with recent makeinfo.
[pwmd.git] / src / crypto.c
blobe09f3800c4bf9fb14b68a851d91a693806e6b532
1 /*
2 Copyright (C) 2006-2021 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 #include <fcntl.h>
26 #include <errno.h>
27 #include <pthread.h>
29 #ifdef WITH_LIBACL
30 #include <sys/acl.h>
31 #endif
33 #include "pwmd-error.h"
34 #include "util-misc.h"
35 #include "common.h"
36 #include "rcfile.h"
37 #include "crypto.h"
38 #include "cache.h"
39 #include "mem.h"
40 #include "util-string.h"
41 #include "rcfile.h"
42 #include "mutex.h"
44 static unsigned keepalive;
45 static pthread_mutex_t crypto_mutex = PTHREAD_MUTEX_INITIALIZER;
47 #define BUFSIZE 4096
49 #define STATUS_TIMEOUT_INIT(crypto) \
50 do { \
51 crypto->status_timeout = time (NULL); \
52 crypto->progress_rc = 0; \
53 } while (0)
55 #define STATUS_TIMEOUT_TEST(crypto, rc, s, line) \
56 do { \
57 time_t now = time (NULL); \
58 if (now - crypto->status_timeout >= keepalive && crypto->client_ctx) { \
59 rc = send_status (crypto->client_ctx, s, line); \
60 crypto->status_timeout = now; \
61 } \
62 } while (0)
64 static gpg_error_t
65 get_password_file (const char *keyfile, unsigned char **result, size_t *len)
67 struct stat st;
68 int fd;
69 unsigned char *buf = NULL;
70 gpg_error_t rc = 0;
72 log_write (_ ("obtaining passphrase from passphrase file"));
73 rc = open_check_file (keyfile, &fd, &st, 0);
74 if (rc)
75 return rc;
77 buf = xmalloc (st.st_size+1);
78 if (buf)
80 size_t rlen = read (fd, buf, st.st_size);
82 if (rlen != st.st_size)
83 rc = GPG_ERR_ASS_READ_ERROR;
84 else
86 buf[rlen] = 0;
87 /* The passphrase may have been truncated do to a nul byte before the
88 * EOF. Better to return an error here rather than passing the
89 * truncated passphrase on. */
90 if (rlen && strlen ((char *)buf) != rlen)
91 rc = GPG_ERR_INV_PASSPHRASE;
93 if (!rc)
95 *result = buf;
96 *len = rlen;
100 else
101 rc = GPG_ERR_ENOMEM;
103 close (fd);
104 if (rc)
105 xfree (buf);
107 return rc;
110 static gpgme_error_t
111 status_cb (void *data, const char *keyword, const char *args)
113 struct crypto_s *crypto = data;
115 // Cache pushing.
116 if (!crypto->client_ctx)
117 return 0;
119 if (!strcmp (keyword, "INQUIRE_MAXLEN") &&
120 (crypto->flags & CRYPTO_FLAG_KEYFILE))
121 return 0;
123 return assuan_write_status (crypto->client_ctx, keyword, args);
126 static gpgme_error_t
127 passphrase_cb (void *data, const char *hint, const char *info, int bad, int fd)
129 struct crypto_s *crypto = data;
130 unsigned char *result = NULL;
131 size_t len;
132 gpg_error_t rc = 0;
134 if (crypto->flags & CRYPTO_FLAG_KEYFILE)
135 rc = get_password_file (crypto->keyfile, &result, &len);
136 else
138 if (hint)
139 rc = assuan_write_status (crypto->client_ctx, "PASSPHRASE_HINT", hint);
141 if (!rc && info)
142 rc = assuan_write_status (crypto->client_ctx, "PASSPHRASE_INFO", info);
144 if (!rc)
146 const char *keyword = "PASSPHRASE";
148 if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD_SIGN)
149 keyword = "SIGN_PASSPHRASE";
150 else if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD_NEW)
152 crypto->flags |= CRYPTO_FLAG_PASSWD_SIGN;
153 keyword = "NEW_PASSPHRASE";
155 else if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD)
156 crypto->flags |= CRYPTO_FLAG_PASSWD_NEW;
157 else if (!bad && crypto->flags & CRYPTO_FLAG_NEWFILE)
159 keyword = "NEW_PASSPHRASE";
160 if (crypto->save.sigkey)
161 crypto->flags |= CRYPTO_FLAG_PASSWD_SIGN;
164 rc = assuan_inquire (crypto->client_ctx, keyword, &result, &len, 0);
168 if (!rc)
170 pthread_cleanup_push ((void *)xfree, result);
172 if (!len)
173 gpgme_io_writen (fd, "\n", 1);
174 else
176 int nl = result[len-1] == '\n';
177 int ret;
179 ret = gpgme_io_writen (fd, result, len);
180 if (!ret && !nl)
181 gpgme_io_writen (fd, "\n", 1);
182 else if (ret)
183 rc = GPG_ERR_CANCELED;
186 pthread_cleanup_pop (1);
189 return rc;
192 static void
193 progress_cb (void *data, const char *what, int type, int current, int total)
195 struct crypto_s *crypto = data;
197 crypto->progress_rc = send_status (crypto->client_ctx, STATUS_GPGME,
198 "%s %i %i %i", what, type, current, total);
201 gpgme_error_t
202 crypto_data_to_buf (const gpgme_data_t data, unsigned char **result,
203 size_t *rlen)
205 off_t ret = gpgme_data_seek (data, 0, SEEK_SET);
206 gpgme_error_t rc;
207 size_t total = 0, size = BUFSIZE;
208 unsigned char *buf = NULL;
210 *result = NULL;
211 *rlen = 0;
213 if (ret == -1)
214 return gpg_error_from_syserror ();
216 buf = xmalloc (size);
217 if (!buf)
218 return GPG_ERR_ENOMEM;
222 ret = gpgme_data_read (data, &buf[total], BUFSIZE);
223 if (ret > 0)
225 unsigned char *p;
227 total += ret;
228 size += BUFSIZE;
229 p = xrealloc (buf, size * sizeof (unsigned char));
230 if (!p)
232 xfree (buf);
233 return GPG_ERR_ENOMEM;
236 buf = p;
238 } while (ret > 0);
240 if (ret == -1)
242 rc = gpgme_err_code_from_syserror ();
243 xfree (buf);
244 return rc;
247 if (!total)
248 xfree (buf);
249 else
250 *result = buf;
252 *rlen = total;
253 return 0;
256 gpgme_error_t
257 crypto_list_keys (struct crypto_s *crypto, char *keys[], int secret,
258 gpgme_key_t **result)
260 gpgme_error_t rc;
261 gpgme_key_t key = NULL, *res = NULL;
262 size_t total = 0;
264 rc = gpgme_op_keylist_ext_start (crypto->ctx, (const char **)keys, secret, 0);
265 if (rc)
266 return rc;
268 STATUS_TIMEOUT_INIT (crypto);
271 gpgme_key_t *p;
273 pthread_cleanup_push ((void *)crypto_free_key_list, res);
274 rc = gpgme_op_keylist_next (crypto->ctx, &key);
275 pthread_cleanup_pop (0);
276 if (rc && gpgme_err_code(rc) != GPG_ERR_EOF)
277 break;
279 if (rc)
281 rc = 0;
282 break;
285 p = xrealloc (res, (total+2) * sizeof (gpgme_key_t));
286 if (!p)
288 rc = GPG_ERR_ENOMEM;
289 break;
292 res = p;
293 res[total++] = key;
294 res[total] = NULL;
295 pthread_cleanup_push ((void *)crypto_free_key_list, res);
296 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_KEEPALIVE, NULL);
297 pthread_cleanup_pop (0);
298 } while (!rc);
300 if (!rc)
302 rc = gpgme_op_keylist_end (crypto->ctx);
303 if (!rc)
305 *result = res;
306 rc = total ? 0 : secret ? GPG_ERR_NO_SECKEY : GPG_ERR_NO_PUBKEY;
309 else
310 crypto_free_key_list (res);
312 return rc;
315 void
316 crypto_free_save (struct save_s *save)
318 if (!save)
319 return;
321 strv_free (save->pubkey);
322 xfree (save->sigkey);
323 xfree (save->userid);
324 xfree (save->algo);
325 crypto_free_key_list (save->mainkey);
327 memset (save, 0, sizeof (struct save_s));
330 static void
331 free_gpgme_data_cb (void *data)
333 gpgme_data_t d = data;
334 char *t;
335 size_t len;
337 if (!data)
338 return;
340 t = gpgme_data_release_and_get_mem (d, &len);
341 if (t)
342 wipememory (t, 0, len);
344 gpgme_free (t);
347 void
348 crypto_free_non_keys (struct crypto_s *crypto)
350 if (!crypto)
351 return;
353 if (crypto->ctx)
354 gpgme_release (crypto->ctx);
356 crypto->ctx = NULL;
357 xfree (crypto->plaintext);
358 crypto->plaintext = NULL;
359 crypto->plaintext_size = 0;
361 if (crypto->cipher)
362 free_gpgme_data_cb (crypto->cipher);
364 crypto->cipher = NULL;
365 crypto_free_save (&crypto->save);
366 xfree (crypto->keyfile);
367 crypto->keyfile = NULL;
368 crypto->flags &= ~CRYPTO_FLAG_KEYFILE;
371 void
372 crypto_free (struct crypto_s *crypto)
374 if (!crypto)
375 return;
377 crypto_free_non_keys (crypto);
378 strv_free (crypto->pubkey);
379 xfree (crypto->sigkey);
380 xfree (crypto->filename);
381 xfree (crypto);
384 gpgme_error_t
385 crypto_init_ctx (struct crypto_s *crypto, int no_pinentry,
386 char *passphrase_file)
388 gpgme_ctx_t ctx;
389 gpgme_keylist_mode_t keylist_mode;
390 gpgme_error_t rc;
392 rc = gpgme_new (&ctx);
393 if (rc)
394 return rc;
396 rc = gpgme_set_protocol (ctx, GPGME_PROTOCOL_OPENPGP);
397 if (!rc)
399 keylist_mode = gpgme_get_keylist_mode (ctx);
400 keylist_mode |= GPGME_KEYLIST_MODE_LOCAL|GPGME_KEYLIST_MODE_WITH_SECRET;
401 rc = gpgme_set_keylist_mode (ctx, keylist_mode);
402 if (!rc)
404 if (no_pinentry || passphrase_file)
405 rc = gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_LOOPBACK);
406 else
407 rc = gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_DEFAULT);
409 if (!rc)
411 gpgme_set_ctx_flag (ctx, "no-symkey-cache", "1");
412 gpgme_set_passphrase_cb (ctx, passphrase_cb, crypto);
413 gpgme_set_progress_cb (ctx, progress_cb, crypto);
414 gpgme_set_status_cb (ctx, status_cb, crypto);
415 crypto->ctx = ctx;
416 crypto->flags = 0;
418 if (passphrase_file)
420 crypto->keyfile = passphrase_file;
421 crypto->flags |= CRYPTO_FLAG_KEYFILE;
427 if (rc)
428 gpgme_release (ctx);
430 return rc;
433 void
434 crypto_set_keepalive ()
436 keepalive = config_get_integer ("global", "keepalive_interval");
439 gpg_error_t
440 crypto_init (struct crypto_s **crypto, void *ctx, const char *filename,
441 int no_pinentry, char *passphrase_file)
443 struct crypto_s *new = xcalloc (1, sizeof (struct crypto_s));
444 gpgme_error_t rc;
446 crypto_set_keepalive ();
448 if (!new)
449 return GPG_ERR_ENOMEM;
451 rc = crypto_init_ctx (new, no_pinentry, passphrase_file);
452 if (rc)
453 goto fail;
455 if (filename)
457 new->filename = str_dup (filename);
458 if (!new->filename)
460 rc = GPG_ERR_ENOMEM;
461 goto fail;
465 new->client_ctx = ctx;
466 *crypto = new;
467 return 0;
469 fail:
470 crypto_free (new);
471 return rc;
474 /* Converts a 40 byte key id to the 16 byte form. Needed for comparison of
475 * gpgme_recipient_t.keyid. */
476 gpg_error_t
477 crypto_keyid_to_16b_once (char *key)
479 size_t len = strlen (key);
481 if (len < 16)
482 return GPG_ERR_INV_ARG;
484 memmove (&key[0], &key[len-16], 16);
485 key[16] = 0;
486 return 0;
489 gpg_error_t
490 crypto_keyid_to_16b (char **keys)
492 char **p;
494 for (p = keys; p && *p; p++)
496 gpg_error_t rc = crypto_keyid_to_16b_once (*p);
497 if (rc)
498 return rc;
501 return 0;
504 gpgme_error_t
505 crypto_decrypt (struct client_s *client, struct crypto_s *crypto)
507 gpgme_data_t plain;
508 gpgme_error_t rc;
509 gpgme_data_t cipher;
510 int fd = -1;
511 struct stat st;
512 char **new_recipients = NULL;
513 char **new_signers = NULL;
514 char **pp;
515 gpgme_decrypt_result_t result;
517 rc = gpgme_data_new (&plain);
518 if (rc)
519 return rc;
521 if (gpgme_check_version ("1.16.0"))
523 gpgme_data_set_flag (plain, "io-buffer-size", "4096");
524 gpgme_data_set_flag (plain, "sensitive", "1");
527 pthread_cleanup_push ((void *)free_gpgme_data_cb, plain);
528 rc = open_check_file (crypto->filename, &fd, &st, 1);
529 if (!rc)
531 pthread_cleanup_push ((void *)close_fd_cb, &fd);
532 rc = gpgme_data_new_from_fd (&cipher, fd);
533 if (!rc)
535 pthread_cleanup_push ((void *)free_gpgme_data_cb, cipher);
536 rc = send_status (client ? client->ctx : NULL, STATUS_DECRYPT, NULL);
537 if (!rc)
539 MUTEX_TRYLOCK ((client ? client->ctx : NULL), &crypto_mutex, rc,
540 (client ? client->lock_timeout : -1));
541 if (!rc)
543 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
544 rc = gpgme_op_decrypt_verify_start (crypto->ctx, cipher, plain);
545 if (!rc)
547 STATUS_TIMEOUT_INIT(crypto);
550 if (!rc && crypto->progress_rc)
551 rc = crypto->progress_rc;
552 if (!rc)
553 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_DECRYPT, NULL);
554 TEST_CANCEL ();
555 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
557 pthread_cleanup_pop (1); // release_mutex_cb
560 pthread_cleanup_pop (1); // free_gpgme_data_cb (cipher)
563 pthread_cleanup_pop (1); // close (fd)
566 pthread_cleanup_pop (0); // free_gpgme_data_cb (plain)
568 if (rc)
570 free_gpgme_data_cb (plain);
571 return rc;
574 pthread_cleanup_push ((void *)free_gpgme_data_cb, plain);
575 result = gpgme_op_decrypt_result (crypto->ctx);
576 if (!result->unsupported_algorithm && !result->wrong_key_usage)
578 gpgme_recipient_t r;
580 for (r = result->recipients; r; r = r->next)
582 pthread_cleanup_push ((void *)strv_free, new_recipients);
583 log_write1 (_ ("%s: recipient: %s, status=%u"),
584 crypto->filename, r->keyid, r->status);
585 pthread_cleanup_pop (0);
586 pp = strv_cat(new_recipients, str_dup (r->keyid));
587 if (!pp)
589 rc = GPG_ERR_ENOMEM;
590 break;
593 new_recipients = pp;
596 else if (result->wrong_key_usage)
597 rc = GPG_ERR_WRONG_KEY_USAGE;
598 else if (result->unsupported_algorithm)
599 rc = GPG_ERR_UNSUPPORTED_ALGORITHM;
601 if (!rc)
603 gpgme_verify_result_t verify;
604 gpgme_signature_t s;
606 verify = gpgme_op_verify_result (crypto->ctx);
607 for (s = verify->signatures; s; s = s->next)
609 unsigned flags = s->summary;
611 pthread_cleanup_push ((void *)strv_free, new_signers);
612 log_write1 (_ ("%s: signer: %s, status=%u"),
613 crypto->filename, s->fpr, s->status);
614 pthread_cleanup_pop (0);
616 flags &= ~(GPGME_SIGSUM_KEY_EXPIRED|GPGME_SIGSUM_SIG_EXPIRED);
617 if (!flags)
618 flags |= GPGME_SIGSUM_VALID;
620 if (gpg_err_code (s->status) == GPG_ERR_KEY_EXPIRED)
621 s->status = 0;
623 if (s->status || s->wrong_key_usage || !(flags & GPGME_SIGSUM_VALID))
624 continue;
626 pp = strv_cat (new_signers, str_dup (s->fpr));
627 if (!pp)
629 rc = GPG_ERR_ENOMEM;
630 break;
633 new_signers = pp;
636 if (verify->signatures && !new_signers)
637 rc = GPG_ERR_BAD_SIGNATURE;
639 if (!rc)
641 xfree (crypto->plaintext);
642 crypto->plaintext = NULL;
643 crypto->plaintext_size = 0;
644 pthread_cleanup_push ((void *)strv_free, new_recipients);
645 pthread_cleanup_push ((void *)strv_free, new_signers);
646 rc = crypto_data_to_buf (plain, &crypto->plaintext,
647 &crypto->plaintext_size);
648 pthread_cleanup_pop (0);
649 pthread_cleanup_pop (0);
650 if (!rc)
652 strv_free (crypto->pubkey);
653 crypto->pubkey = new_recipients;
654 crypto_keyid_to_16b (crypto->pubkey);
656 xfree (crypto->sigkey);
657 crypto->sigkey = NULL;
658 if (new_signers)
660 crypto->sigkey = str_dup (*new_signers);
661 strv_free (new_signers);
662 crypto_keyid_to_16b_once (crypto->sigkey);
668 if (rc)
670 strv_free (new_recipients);
671 strv_free (new_signers);
674 pthread_cleanup_pop (1); // free_gpgme_data_cb (plain)
675 return rc;
678 void
679 crypto_free_key_list (gpgme_key_t *keys)
681 int i;
683 for (i = 0; keys && keys[i]; i++)
684 gpgme_key_unref (keys[i]);
686 xfree (keys);
689 /* Removes strings in 'prune' from 'a'. */
690 static char **
691 prune_keys (char **a, char **prune)
693 char **p;
695 for (p = prune; p && *p; p++)
697 char **ap;
699 for (ap = a; ap && *ap; ap++)
701 if (!strcmp (*ap, *p))
703 while (*ap)
705 *ap = *(ap+1);
706 ap++;
712 return a;
715 static void
716 remove_duplicates (char **a)
718 char **p;
720 for (p = a; p && *p; p++)
722 char **t;
724 for (t = p+1; t && *t; t++)
726 if (!strcmp (*p, *t))
728 char *tmp = *t;
730 while (*(t+1))
732 *t = *(t+1);
733 t++;
736 *t = NULL;
737 xfree (tmp);
738 remove_duplicates (a);
739 return;
745 gpgme_error_t
746 crypto_encrypt (struct client_s *client, struct crypto_s *crypto)
748 gpgme_error_t rc;
749 gpgme_data_t cipher = NULL;
750 gpgme_key_t *keys = NULL;
751 gpgme_key_t *sigkeys = NULL;
752 unsigned flags = 0;
753 int sign = 0;
755 if (!((crypto->flags & CRYPTO_FLAG_SYMMETRIC)))
757 crypto_keyid_to_16b (crypto->save.pubkey);
758 remove_duplicates (crypto->save.pubkey);
759 rc = crypto_list_keys (crypto, crypto->save.pubkey, 0, &keys);
760 if (rc)
761 return rc;
764 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
765 rc = gpgme_data_new (&cipher);
766 pthread_cleanup_push ((void *)free_gpgme_data_cb, cipher);
767 if (!rc)
768 rc = gpgme_data_set_file_name (cipher, crypto->filename);
770 if (!rc && crypto->save.sigkey)
772 char **tmp = NULL;
774 crypto_keyid_to_16b_once (crypto->save.sigkey);
775 strv_printf (&tmp, "%s", crypto->save.sigkey);
776 pthread_cleanup_push ((void *)strv_free, tmp);
777 rc = crypto_list_keys (crypto, tmp, 1, &sigkeys);
778 pthread_cleanup_pop (1);
779 if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
780 rc = 0;
783 if (!rc)
785 gpgme_data_t plain = NULL;
787 pthread_cleanup_push ((void *)crypto_free_key_list, sigkeys);
788 rc = gpgme_data_new_from_mem (&plain, (char *)crypto->plaintext,
789 crypto->plaintext_size, 0);
790 pthread_cleanup_push ((void *)free_gpgme_data_cb, plain);
791 if (!rc)
793 int i;
795 gpgme_signers_clear (crypto->ctx);
797 for (i = 0; sigkeys && sigkeys[i]; i++)
798 gpgme_signers_add (crypto->ctx, sigkeys[i]);
801 if (!rc)
803 gpgme_data_set_encoding (cipher, GPGME_DATA_ENCODING_ARMOR);
804 rc = send_status (client ? client->ctx : NULL, STATUS_ENCRYPT, NULL);
807 if (!rc)
809 int f = config_get_boolean ("global", "encrypt_to");
811 if (!f)
812 flags |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
814 f = config_get_boolean ("global", "always_trust");
815 if (f)
816 flags |= GPGME_ENCRYPT_ALWAYS_TRUST;
818 if (!(crypto->flags & CRYPTO_FLAG_SYMMETRIC)
819 || (crypto->flags & CRYPTO_FLAG_SYMMETRIC && sigkeys))
820 sign = 1;
823 if (!rc)
824 MUTEX_TRYLOCK ((client ? client->ctx : NULL), &crypto_mutex, rc,
825 (client ? client->lock_timeout : -1));
827 if (!rc)
829 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
830 if (sign)
831 rc = gpgme_op_encrypt_sign_start (crypto->ctx, keys, flags, plain,
832 cipher);
833 else
834 rc = gpgme_op_encrypt_start (crypto->ctx, NULL, flags, plain,
835 cipher);
836 if (!rc)
838 STATUS_TIMEOUT_INIT (crypto);
841 if (!rc && crypto->progress_rc)
842 rc = crypto->progress_rc;
843 if (!rc)
844 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_ENCRYPT, NULL);
845 TEST_CANCEL();
846 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
848 pthread_cleanup_pop (1);
850 if (!rc)
852 gpgme_encrypt_result_t result;
853 gpgme_sign_result_t sresult;
854 gpgme_invalid_key_t inv;
855 gpgme_new_signature_t sigs;
856 char **prune = NULL;
857 char **p = NULL;
859 result = gpgme_op_encrypt_result (crypto->ctx);
860 inv = result->invalid_recipients;
861 while (inv)
863 pthread_cleanup_push ((void *)strv_free, prune);
864 log_write1 (_ ("%s: invalid recipient: %s, rc=%u"),
865 crypto->filename, inv->fpr, inv->reason);
866 pthread_cleanup_pop (0);
867 p = strv_cat (prune, str_dup(inv->fpr));
868 if (!p)
870 rc = GPG_ERR_ENOMEM;
871 strv_free (prune);
872 break;
875 prune = p;
876 inv = inv->next;
879 if (prune)
881 p = prune_keys (crypto->save.pubkey, prune);
882 crypto->save.pubkey = p;
883 strv_free (prune);
886 crypto_keyid_to_16b (crypto->save.pubkey);
887 sresult = gpgme_op_sign_result (crypto->ctx);
888 inv = sresult ? sresult->invalid_signers : NULL;
889 while (!rc && inv)
891 log_write1 (_ ("%s: invalid signer: %s, rc=%u"),
892 crypto->filename, inv->fpr, inv->reason);
893 inv = inv->next;
896 sigs = sresult ? sresult->signatures : NULL;
897 if (!rc && sigs)
899 p = NULL;
901 while (sigs)
903 char **pp;
905 pthread_cleanup_push ((void *)strv_free, p);
906 log_write1 (_ ("%s: signer: %s"), crypto->filename,
907 sigs->fpr);
908 pthread_cleanup_pop (0);
910 pp = strv_cat (p, str_dup (sigs->fpr));
911 if (!pp)
913 rc = GPG_ERR_ENOMEM;
914 strv_free (p);
915 break;
918 p = pp;
919 sigs = sigs->next;
922 if (!rc)
924 xfree (crypto->save.sigkey);
925 crypto->save.sigkey = str_dup (*p);
926 strv_free (p);
927 crypto_keyid_to_16b_once (crypto->save.sigkey);
928 crypto->cipher = cipher;
931 else if (!rc && crypto->flags & CRYPTO_FLAG_SYMMETRIC)
933 crypto->cipher = cipher;
935 else if (!rc)
937 if (!(crypto->flags & CRYPTO_FLAG_SYMMETRIC)
938 || (crypto->flags & CRYPTO_FLAG_SYMMETRIC && sigkeys))
939 rc = GPG_ERR_NO_SIGNATURE_SCHEME;
944 pthread_cleanup_pop (1); // free_gpgme_data_cb (plain)
945 pthread_cleanup_pop (1); // crypto_free_key_list (sigkeys)
948 pthread_cleanup_pop (0); // free_gpgme_data_cb (cipher)
949 pthread_cleanup_pop (1); // crypto_free_key_list (keys)
951 if (rc)
952 free_gpgme_data_cb (cipher);
954 return rc;
957 gpgme_error_t
958 crypto_passwd (struct client_s *client, struct crypto_s *crypto)
960 gpgme_error_t rc;
961 gpgme_key_t *keys = NULL;
963 /* Use SAVE instead for symmetric files. */
964 rc = crypto_is_symmetric (client->filename);
965 if (!rc || rc != GPG_ERR_BAD_DATA)
966 return !rc ? GPG_ERR_NOT_SUPPORTED : rc;
968 /* Cannot change the passphrase of a key stored on a smartcard. Use
969 * gpg --card-edit instead. */
970 rc = cache_is_shadowed (client->filename);
971 if (!rc)
972 return GPG_ERR_NOT_SUPPORTED;
973 else if (rc != GPG_ERR_NO_DATA)
974 return rc;
976 rc = crypto_list_keys (crypto, crypto->pubkey, 1, &keys);
977 if (rc)
978 return rc;
980 crypto->flags |= CRYPTO_FLAG_PASSWD;
981 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
982 rc = send_status (client->ctx, STATUS_KEEPALIVE, NULL);
983 if (!rc)
984 MUTEX_TRYLOCK (client->ctx, &crypto_mutex, rc, client->lock_timeout);
986 if (!rc)
988 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
989 rc = gpgme_op_passwd_start (crypto->ctx, keys[0], 0);
990 if (!rc)
992 STATUS_TIMEOUT_INIT (crypto);
995 if (!rc && crypto->progress_rc)
996 rc = crypto->progress_rc;
997 if (!rc)
998 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_KEEPALIVE, NULL);
999 TEST_CANCEL();
1000 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
1002 pthread_cleanup_pop (1);
1005 pthread_cleanup_pop (1);
1006 return rc;
1009 /* Generate a new key pair. The resulting keyid's are stored in crypto->save.
1011 gpgme_error_t
1012 crypto_genkey (struct client_s *client, struct crypto_s *crypto)
1014 gpgme_error_t rc;
1016 rc = send_status (client ? client->ctx : NULL, STATUS_GENKEY, NULL);
1017 if (!rc)
1018 MUTEX_TRYLOCK ((client ? client->ctx : NULL), &crypto_mutex, rc,
1019 (client ? client->lock_timeout : 0));
1021 if (!rc)
1023 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
1024 if (crypto->save.mainkey)
1026 rc = gpgme_op_createsubkey_start (crypto->ctx,
1027 crypto->save.mainkey[0],
1028 crypto->save.algo,
1030 crypto->save.expire,
1031 crypto->save.flags);
1033 else
1035 rc = gpgme_op_createkey_start (crypto->ctx,
1036 crypto->save.userid,
1037 crypto->save.algo,
1039 crypto->save.expire,
1040 NULL,
1041 crypto->save.flags);
1044 if (!rc)
1046 STATUS_TIMEOUT_INIT (crypto);
1049 if (!rc && crypto->progress_rc)
1050 rc = crypto->progress_rc;
1051 if (!rc)
1052 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_GENKEY, NULL);
1053 TEST_CANCEL();
1054 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
1056 pthread_cleanup_pop (1);
1059 if (!rc)
1061 gpgme_key_t *keys = NULL;
1062 gpgme_genkey_result_t result;
1064 result = gpgme_op_genkey_result (crypto->ctx);
1065 xfree (crypto->save.sigkey);
1066 crypto->save.sigkey = str_dup (result->fpr);
1067 crypto_keyid_to_16b_once (crypto->save.sigkey);
1069 if (!rc)
1071 char **tmp = NULL;
1073 strv_printf (&tmp, "%s", crypto->save.sigkey);
1074 pthread_cleanup_push ((void *)strv_free, tmp);
1075 rc = crypto_list_keys (crypto, tmp, 1, &keys);
1076 pthread_cleanup_pop (1);
1079 if (!rc)
1081 gpgme_subkey_t key = keys[0]->subkeys;
1083 for (; key; key = key->next)
1085 if (key->can_encrypt)
1086 break;
1089 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
1090 rc = send_status (client ? client->ctx : NULL, STATUS_GENKEY, "%s %s",
1091 crypto->save.sigkey, key ? key->fpr : "");
1092 if (!rc && key)
1094 crypto->save.pubkey = strv_cat (crypto->save.pubkey,
1095 str_dup (key->fpr));
1096 crypto_keyid_to_16b (crypto->save.pubkey);
1099 pthread_cleanup_pop (1);
1103 return rc;
1106 #ifdef WITH_LIBACL
1107 static void
1108 acl_free_cb (void *arg)
1110 acl_t acl = arg ? (acl_t) arg : NULL;
1112 if (acl)
1113 acl_free (acl);
1115 #endif
1117 /* The advisory lock should be obtained before calling this function. */
1118 gpg_error_t
1119 crypto_write_file (struct crypto_s *crypto, unsigned char **r_crc,
1120 size_t *r_crclen)
1122 unsigned char *buf;
1123 size_t size, len;
1124 int fd;
1125 gpg_error_t rc;
1126 char tmp[PATH_MAX];
1127 struct stat st;
1128 mode_t mode = 0600;
1129 #ifdef WITH_LIBACL
1130 acl_t acl = NULL;
1131 #endif
1133 if (crypto->filename)
1135 if (lstat (crypto->filename, &st) == 0)
1137 mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
1139 if (!(mode & S_IWUSR))
1140 return GPG_ERR_EACCES;
1142 else if (errno != ENOENT)
1143 return gpg_error_from_errno (errno);
1145 snprintf (tmp, sizeof (tmp), "%s.XXXXXX", crypto->filename);
1146 mode_t tmode = umask (0600);
1147 fd = mkstemp (tmp);
1148 if (fd == -1)
1150 rc = gpg_error_from_errno (errno);
1151 umask (tmode);
1152 log_write ("%s: %s", tmp, pwmd_strerror (rc));
1153 return rc;
1156 umask (tmode);
1158 else
1159 fd = STDOUT_FILENO;
1161 rc = crypto_data_to_buf (crypto->cipher, &buf, &size);
1162 if (rc)
1164 if (crypto->filename)
1165 close (fd);
1166 return rc;
1169 pthread_cleanup_push ((void *)close_fd_cb, &fd);
1170 if (r_crc)
1171 rc = get_checksum_memory (buf, size, r_crc, r_crclen);
1173 if (!rc)
1175 pthread_cleanup_push ((void *)xfree, buf);
1176 len = write (fd, buf, size);
1177 pthread_cleanup_pop (1);
1178 if (len != size)
1179 rc = gpg_error_from_errno (errno);
1182 if (!rc)
1184 if (fsync (fd) != -1)
1186 if (crypto->filename && close (fd) != -1)
1188 #ifdef WITH_LIBACL
1189 acl = acl_get_file (crypto->filename, ACL_TYPE_ACCESS);
1190 if (!acl && errno == ENOENT)
1191 acl = acl_get_file (".", ACL_TYPE_DEFAULT);
1192 if (!acl)
1193 log_write ("ACL: %s: %s", crypto->filename,
1194 pwmd_strerror (gpg_error_from_errno (errno)));
1195 pthread_cleanup_push ((void *)acl_free_cb, acl);
1196 #endif
1198 fd = -1;
1199 if (config_get_boolean (crypto->filename, "backup"))
1201 char tmp2[PATH_MAX];
1203 snprintf (tmp2, sizeof (tmp2), "%s.backup", crypto->filename);
1204 if (rename (crypto->filename, tmp2) == -1)
1205 if (errno != ENOENT)
1206 rc = gpg_error_from_errno (errno);
1209 if (!rc && rename (tmp, crypto->filename) == -1)
1210 rc = gpg_error_from_errno (errno);
1212 if (!rc)
1214 if (chmod (crypto->filename, mode) == -1)
1215 log_write ("%s(%u): %s", __FILE__, __LINE__,
1216 pwmd_strerror (gpg_error_from_syserror ()));
1218 #ifdef WITH_LIBACL
1219 if (!rc && acl && acl_set_file (crypto->filename,
1220 ACL_TYPE_ACCESS, acl))
1221 log_write ("ACL: %s: %s", crypto->filename,
1222 pwmd_strerror (gpg_error_from_errno (errno)));
1223 pthread_cleanup_pop (1);
1224 #endif
1226 else if (crypto->filename)
1227 rc = gpg_error_from_errno (errno);
1229 if (!rc && fd != -1)
1231 char *datadir = str_asprintf ("%s/data", homedir);
1233 if (datadir)
1235 int dfd = open (datadir, O_RDONLY);
1237 if (dfd != -1)
1239 if (fsync (dfd) == -1)
1240 log_write ("%s %d: %s", __FILE__, __LINE__,
1241 pwmd_strerror (errno));
1243 close (dfd);
1245 else
1246 log_write ("%s %d: %s", __FILE__, __LINE__,
1247 pwmd_strerror (errno));
1249 xfree (datadir);
1253 else
1254 rc = gpg_error_from_errno (errno);
1257 pthread_cleanup_pop (0); // close (fd)
1258 if (fd != -1)
1259 close (fd);
1261 return rc;
1264 char *
1265 crypto_key_info (const gpgme_key_t key)
1267 struct string_s *string = string_new (NULL), *s;
1268 char *line = NULL;
1269 unsigned n, u;
1270 gpgme_subkey_t subkey;
1271 gpgme_user_id_t uid;
1273 if (!string)
1274 return NULL;
1276 for (u = 0, uid = key->uids; uid; uid = uid->next)
1277 u++;
1279 for (n = 0, subkey = key->subkeys; subkey; subkey = subkey->next)
1280 n++;
1282 s = string_append_printf (string, "%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%i:%s:%s:%s:%i:%u:%u",
1283 key->revoked, key->expired, key->disabled,
1284 key->invalid, key->can_encrypt, key->can_sign,
1285 key->can_certify, key->secret,
1286 key->can_authenticate, key->is_qualified,
1287 key->protocol,
1288 key->issuer_serial ? key->issuer_serial : "",
1289 key->issuer_name ? key->issuer_name : "",
1290 key->chain_id ? key->chain_id : "",
1291 key->owner_trust, u, n);
1292 if (!s)
1294 string_free (string, 1);
1295 return NULL;
1298 string = s;
1299 for (subkey = key->subkeys; subkey; subkey = subkey->next)
1301 char *tmp;
1303 s = string_append_printf (string, ":%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%i:%u",
1304 subkey->revoked, subkey->expired,
1305 subkey->disabled, subkey->invalid,
1306 subkey->can_encrypt, subkey->can_sign,
1307 subkey->can_certify, subkey->secret,
1308 subkey->can_authenticate, subkey->is_qualified,
1309 subkey->is_cardkey, subkey->pubkey_algo,
1310 subkey->length);
1311 if (!s)
1313 string_free (string, 1);
1314 return NULL;
1317 string = s;
1318 s = string_append_printf (string, ":%s:%s:%s:%li:%li:%s",
1319 subkey->keyid, subkey->fpr,
1320 subkey->keygrip ? subkey->keygrip : "",
1321 subkey->timestamp, subkey->expires,
1322 subkey->card_number ? subkey->card_number : "0");
1323 if (!s)
1325 string_free (string, 1);
1326 return NULL;
1329 string = s;
1330 tmp = gnupg_escape (subkey->curve);
1331 s = string_append_printf (string, ":%s", tmp ? tmp : "");
1332 xfree (tmp);
1333 if (!s)
1335 string_free (string, 1);
1336 return NULL;
1339 string = s;
1342 for (uid = key->uids; uid; uid = uid->next)
1344 char *userid, *name, *email, *comment;
1346 userid = gnupg_escape (uid->uid);
1347 name = gnupg_escape (uid->name);
1348 email = gnupg_escape (uid->email);
1349 comment = gnupg_escape (uid->comment);
1350 s = string_append_printf (string, ":%u:%u:%u:%s:%s:%s:%s",
1351 uid->revoked, uid->invalid, uid->validity,
1352 userid ? userid : "",
1353 name ? name : "",
1354 email ? email : "",
1355 comment ? comment : "");
1356 xfree (userid);
1357 xfree (name);
1358 xfree (email);
1359 xfree (comment);
1360 if (!s)
1362 string_free (string, 1);
1363 return NULL;
1366 string = s;
1369 line = string->str;
1370 string_free (string, 0);
1371 return line;
1374 gpg_error_t
1375 crypto_try_decrypt (struct client_s *client, int no_pinentry)
1377 struct crypto_s *crypto;
1378 gpg_error_t rc;
1379 char *keyfile = config_get_string (client->filename, "passphrase_file");
1381 rc = crypto_init (&crypto, client->ctx, client->filename, no_pinentry,
1382 keyfile);
1383 if (!rc)
1385 pthread_cleanup_push ((void *)crypto_free, crypto);
1386 rc = crypto_decrypt (client, crypto);
1387 pthread_cleanup_pop (1);
1389 else
1390 xfree (keyfile);
1392 return rc;
1395 /* The advisory lock should be obtained before calling this function. */
1396 gpg_error_t
1397 crypto_is_symmetric (const char *filename)
1399 int fd;
1400 uint8_t magic[2];
1401 ssize_t len;
1402 gpg_error_t rc;
1404 rc = open_check_file (filename, &fd, NULL, 1);
1405 if (rc)
1406 return rc;
1408 len = read (fd, &magic, sizeof(magic));
1409 close (fd);
1410 if (len != sizeof (magic))
1411 return GPG_ERR_INV_VALUE;
1413 // Always read as big endian.
1414 if (magic[0] != 0x8c || magic[1] != 0x0d)
1415 return GPG_ERR_BAD_DATA;
1417 return 0;
1420 gpg_error_t
1421 crypto_delete_key (struct client_s *client, struct crypto_s *crypto,
1422 const gpgme_key_t key, int secret)
1424 gpg_error_t rc;
1426 STATUS_TIMEOUT_INIT (crypto);
1427 rc = send_status (client->ctx, STATUS_DECRYPT, NULL);
1428 if (!rc)
1429 rc = gpgme_op_delete_ext_start (crypto->ctx, key, GPGME_DELETE_FORCE
1430 | GPGME_DELETE_ALLOW_SECRET);
1432 if (rc)
1433 return rc;
1437 if (!rc && crypto->progress_rc)
1438 rc = crypto->progress_rc;
1440 if (!rc)
1441 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_DECRYPT, NULL);
1443 if (rc)
1444 break;
1445 } while (!gpgme_wait (crypto->ctx, &rc, 0) && !rc);
1447 return rc;