BULK: Fix recursion of next command results.
[pwmd.git] / src / crypto.c
blobcc5398d4d9a609af33f86bae541f1d79f6828c8c
1 /*
2 Copyright (C) 2006-2018 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 as published by
8 the Free Software Foundation, either version 2 of the License, or
9 (at your option) any later version.
11 Pwmd is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
23 #include <stdio.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <errno.h>
28 #include <pthread.h>
30 #ifdef WITH_LIBACL
31 #include <sys/acl.h>
32 #endif
34 #include "pwmd-error.h"
35 #include "util-misc.h"
36 #include "common.h"
37 #include "rcfile.h"
38 #include "crypto.h"
39 #include "cache.h"
40 #include "mem.h"
41 #include "util-string.h"
42 #include "rcfile.h"
43 #include "mutex.h"
45 static unsigned keepalive;
46 static pthread_mutex_t crypto_mutex = PTHREAD_MUTEX_INITIALIZER;
48 #define BUFSIZE 4096
50 #define STATUS_TIMEOUT_INIT(crypto) \
51 do { \
52 crypto->status_timeout = time (NULL); \
53 crypto->progress_rc = 0; \
54 } while (0)
56 #define STATUS_TIMEOUT_TEST(crypto, rc, s, line) \
57 do { \
58 time_t now = time (NULL); \
59 if (now - crypto->status_timeout >= keepalive && crypto->client_ctx) { \
60 rc = send_status (crypto->client_ctx, s, line); \
61 crypto->status_timeout = now; \
62 } \
63 } while (0)
65 static gpg_error_t
66 get_password_file (const char *keyfile, unsigned char **result, size_t *len)
68 struct stat st;
69 int fd;
70 unsigned char *buf = NULL;
71 gpg_error_t rc = 0;
73 log_write (_ ("obtaining passphrase from passphrase file"));
74 rc = open_check_file (keyfile, &fd, &st, 0);
75 if (rc)
76 return rc;
78 buf = xmalloc (st.st_size+1);
79 if (buf)
81 size_t rlen = read (fd, buf, st.st_size);
83 if (rlen != st.st_size)
84 rc = GPG_ERR_ASS_READ_ERROR;
85 else
87 buf[rlen] = 0;
88 /* The passphrase may have been truncated do to a nul byte before the
89 * EOF. Better to return an error here rather than passing the
90 * truncated passphrase on. */
91 if (rlen && strlen ((char *)buf) != rlen)
92 rc = GPG_ERR_INV_PASSPHRASE;
94 if (!rc)
96 *result = buf;
97 *len = rlen;
101 else
102 rc = GPG_ERR_ENOMEM;
104 close (fd);
105 if (rc)
106 xfree (buf);
108 return rc;
111 static gpgme_error_t
112 status_cb (void *data, const char *keyword, const char *args)
114 struct crypto_s *crypto = data;
116 // Cache pushing.
117 if (!crypto->client_ctx)
118 return 0;
120 if (!strcmp (keyword, "INQUIRE_MAXLEN") &&
121 (crypto->flags & CRYPTO_FLAG_KEYFILE))
122 return 0;
124 return assuan_write_status (crypto->client_ctx, keyword, args);
127 static gpgme_error_t
128 passphrase_cb (void *data, const char *hint, const char *info, int bad, int fd)
130 struct crypto_s *crypto = data;
131 unsigned char *result = NULL;
132 size_t len;
133 gpg_error_t rc = 0;
135 if (crypto->flags & CRYPTO_FLAG_KEYFILE)
136 rc = get_password_file (crypto->keyfile, &result, &len);
137 else
139 if (hint)
140 rc = assuan_write_status (crypto->client_ctx, "PASSPHRASE_HINT", hint);
142 if (!rc && info)
143 rc = assuan_write_status (crypto->client_ctx, "PASSPHRASE_INFO", info);
145 if (!rc)
147 const char *keyword = "PASSPHRASE";
149 if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD_SIGN)
150 keyword = "SIGN_PASSPHRASE";
151 else if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD_NEW)
153 crypto->flags |= CRYPTO_FLAG_PASSWD_SIGN;
154 keyword = "NEW_PASSPHRASE";
156 else if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD)
157 crypto->flags |= CRYPTO_FLAG_PASSWD_NEW;
158 else if (!bad && crypto->flags & CRYPTO_FLAG_NEWFILE)
160 keyword = "NEW_PASSPHRASE";
161 if (crypto->save.sigkey)
162 crypto->flags |= CRYPTO_FLAG_PASSWD_SIGN;
165 rc = assuan_inquire (crypto->client_ctx, keyword, &result, &len, 0);
169 if (!rc)
171 pthread_cleanup_push ((void *)xfree, result);
173 if (!len)
174 gpgme_io_writen (fd, "\n", 1);
175 else
177 int nl = result[len-1] == '\n';
178 int ret;
180 ret = gpgme_io_writen (fd, result, len);
181 if (!ret && !nl)
182 gpgme_io_writen (fd, "\n", 1);
183 else if (ret)
184 rc = GPG_ERR_CANCELED;
187 pthread_cleanup_pop (1);
190 return rc;
193 static void
194 progress_cb (void *data, const char *what, int type, int current, int total)
196 struct crypto_s *crypto = data;
198 crypto->progress_rc = send_status (crypto->client_ctx, STATUS_GPGME,
199 "%s %i %i %i", what, type, current, total);
202 gpgme_error_t
203 crypto_data_to_buf (const gpgme_data_t data, unsigned char **result,
204 size_t *rlen)
206 off_t ret = gpgme_data_seek (data, 0, SEEK_SET);
207 gpgme_error_t rc;
208 size_t total = 0, size = BUFSIZE;
209 unsigned char *buf = NULL;
211 *result = NULL;
212 *rlen = 0;
214 if (ret == -1)
215 return gpg_error_from_syserror ();
217 buf = xmalloc (size);
218 if (!buf)
219 return GPG_ERR_ENOMEM;
223 ret = gpgme_data_read (data, &buf[total], BUFSIZE);
224 if (ret > 0)
226 unsigned char *p;
228 total += ret;
229 size += BUFSIZE;
230 p = xrealloc (buf, size * sizeof (unsigned char));
231 if (!p)
233 xfree (buf);
234 return GPG_ERR_ENOMEM;
237 buf = p;
239 } while (ret > 0);
241 if (ret == -1)
243 rc = gpgme_err_code_from_syserror ();
244 xfree (buf);
245 return rc;
248 if (!total)
249 xfree (buf);
250 else
251 *result = buf;
253 *rlen = total;
254 return 0;
257 gpgme_error_t
258 crypto_list_keys (struct crypto_s *crypto, char *keys[], int secret,
259 gpgme_key_t **result)
261 gpgme_error_t rc;
262 gpgme_key_t key = NULL, *res = NULL;
263 size_t total = 0;
265 rc = gpgme_op_keylist_ext_start (crypto->ctx, (const char **)keys, secret, 0);
266 if (rc)
267 return rc;
269 STATUS_TIMEOUT_INIT (crypto);
272 gpgme_key_t *p;
274 pthread_cleanup_push ((void *)crypto_free_key_list, res);
275 rc = gpgme_op_keylist_next (crypto->ctx, &key);
276 pthread_cleanup_pop (0);
277 if (rc && gpgme_err_code(rc) != GPG_ERR_EOF)
278 break;
280 if (rc)
282 rc = 0;
283 break;
286 p = xrealloc (res, (total+2) * sizeof (gpgme_key_t));
287 if (!p)
289 rc = GPG_ERR_ENOMEM;
290 break;
293 res = p;
294 res[total++] = key;
295 res[total] = NULL;
296 pthread_cleanup_push ((void *)crypto_free_key_list, res);
297 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_KEEPALIVE, NULL);
298 pthread_cleanup_pop (0);
299 } while (!rc);
301 if (!rc)
303 rc = gpgme_op_keylist_end (crypto->ctx);
304 if (!rc)
306 *result = res;
307 rc = total ? 0 : secret ? GPG_ERR_NO_SECKEY : GPG_ERR_NO_PUBKEY;
310 else
311 crypto_free_key_list (res);
313 return rc;
316 void
317 crypto_free_save (struct save_s *save)
319 if (!save)
320 return;
322 strv_free (save->pubkey);
323 xfree (save->sigkey);
324 xfree (save->userid);
325 xfree (save->algo);
326 crypto_free_key_list (save->mainkey);
328 memset (save, 0, sizeof (struct save_s));
331 static void
332 free_gpgme_data_cb (void *data)
334 gpgme_data_t d = data;
335 char *t;
336 size_t len;
338 if (!data)
339 return;
341 t = gpgme_data_release_and_get_mem (d, &len);
342 if (t)
343 wipememory (t, 0, len);
345 gpgme_free (t);
348 void
349 crypto_free_non_keys (struct crypto_s *crypto)
351 if (!crypto)
352 return;
354 if (crypto->ctx)
355 gpgme_release (crypto->ctx);
357 crypto->ctx = NULL;
358 xfree (crypto->plaintext);
359 crypto->plaintext = NULL;
360 crypto->plaintext_size = 0;
362 if (crypto->cipher)
363 free_gpgme_data_cb (crypto->cipher);
365 crypto->cipher = NULL;
366 crypto_free_save (&crypto->save);
367 xfree (crypto->keyfile);
368 crypto->keyfile = NULL;
369 crypto->flags &= ~CRYPTO_FLAG_KEYFILE;
372 void
373 crypto_free (struct crypto_s *crypto)
375 if (!crypto)
376 return;
378 crypto_free_non_keys (crypto);
379 strv_free (crypto->pubkey);
380 xfree (crypto->sigkey);
381 xfree (crypto->filename);
382 xfree (crypto);
385 gpgme_error_t
386 crypto_init_ctx (struct crypto_s *crypto, int no_pinentry,
387 char *passphrase_file)
389 gpgme_ctx_t ctx;
390 gpgme_keylist_mode_t keylist_mode;
391 gpgme_error_t rc;
393 rc = gpgme_new (&ctx);
394 if (rc)
395 return rc;
397 rc = gpgme_set_protocol (ctx, GPGME_PROTOCOL_OPENPGP);
398 if (!rc)
400 keylist_mode = gpgme_get_keylist_mode (ctx);
401 keylist_mode |= GPGME_KEYLIST_MODE_LOCAL|GPGME_KEYLIST_MODE_WITH_SECRET;
402 rc = gpgme_set_keylist_mode (ctx, keylist_mode);
403 if (!rc)
405 if (no_pinentry || passphrase_file)
406 rc = gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_LOOPBACK);
407 else
408 rc = gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_DEFAULT);
410 if (!rc)
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 pthread_cleanup_push ((void *)free_gpgme_data_cb, plain);
522 rc = open_check_file (crypto->filename, &fd, &st, 1);
523 if (!rc)
525 pthread_cleanup_push ((void *)close_fd_cb, &fd);
526 rc = gpgme_data_new_from_fd (&cipher, fd);
527 if (!rc)
529 pthread_cleanup_push ((void *)free_gpgme_data_cb, cipher);
530 rc = send_status (client ? client->ctx : NULL, STATUS_DECRYPT, NULL);
531 if (!rc)
533 MUTEX_TRYLOCK (client->ctx, &crypto_mutex, rc,
534 client->lock_timeout);
535 if (!rc)
537 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
538 rc = gpgme_op_decrypt_verify_start (crypto->ctx, cipher, plain);
539 if (!rc)
541 STATUS_TIMEOUT_INIT(crypto);
544 if (!rc && crypto->progress_rc)
545 rc = crypto->progress_rc;
546 if (!rc)
547 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_DECRYPT, NULL);
548 TEST_CANCEL ();
549 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
551 pthread_cleanup_pop (1); // release_mutex_cb
554 pthread_cleanup_pop (1); // free_gpgme_data_cb (cipher)
557 pthread_cleanup_pop (1); // close (fd)
560 pthread_cleanup_pop (0); // free_gpgme_data_cb (plain)
562 if (rc)
564 free_gpgme_data_cb (plain);
565 return rc;
568 pthread_cleanup_push ((void *)free_gpgme_data_cb, plain);
569 result = gpgme_op_decrypt_result (crypto->ctx);
570 if (!result->unsupported_algorithm && !result->wrong_key_usage)
572 gpgme_recipient_t r;
574 for (r = result->recipients; r; r = r->next)
576 pthread_cleanup_push ((void *)strv_free, new_recipients);
577 log_write1 (_ ("%s: recipient: %s, status=%u"),
578 crypto->filename, r->keyid, r->status);
579 pthread_cleanup_pop (0);
580 pp = strv_cat(new_recipients, str_dup (r->keyid));
581 if (!pp)
583 rc = GPG_ERR_ENOMEM;
584 break;
587 new_recipients = pp;
590 else if (result->wrong_key_usage)
591 rc = GPG_ERR_WRONG_KEY_USAGE;
592 else if (result->unsupported_algorithm)
593 rc = GPG_ERR_UNSUPPORTED_ALGORITHM;
595 if (!rc)
597 gpgme_verify_result_t verify;
598 gpgme_signature_t s;
600 verify = gpgme_op_verify_result (crypto->ctx);
601 for (s = verify->signatures; s; s = s->next)
603 unsigned flags = s->summary;
605 pthread_cleanup_push ((void *)strv_free, new_signers);
606 log_write1 (_ ("%s: signer: %s, status=%u"),
607 crypto->filename, s->fpr, s->status);
608 pthread_cleanup_pop (0);
610 flags &= ~(GPGME_SIGSUM_KEY_EXPIRED|GPGME_SIGSUM_SIG_EXPIRED);
611 if (!flags)
612 flags |= GPGME_SIGSUM_VALID;
614 if (gpg_err_code (s->status) == GPG_ERR_KEY_EXPIRED)
615 s->status = 0;
617 if (s->status || s->wrong_key_usage || !(flags & GPGME_SIGSUM_VALID))
618 continue;
620 pp = strv_cat (new_signers, str_dup (s->fpr));
621 if (!pp)
623 rc = GPG_ERR_ENOMEM;
624 break;
627 new_signers = pp;
630 if (verify->signatures && !new_signers)
631 rc = GPG_ERR_BAD_SIGNATURE;
633 if (!rc)
635 xfree (crypto->plaintext);
636 crypto->plaintext = NULL;
637 crypto->plaintext_size = 0;
638 pthread_cleanup_push ((void *)strv_free, new_recipients);
639 pthread_cleanup_push ((void *)strv_free, new_signers);
640 rc = crypto_data_to_buf (plain, &crypto->plaintext,
641 &crypto->plaintext_size);
642 pthread_cleanup_pop (0);
643 pthread_cleanup_pop (0);
644 if (!rc)
646 strv_free (crypto->pubkey);
647 crypto->pubkey = new_recipients;
648 crypto_keyid_to_16b (crypto->pubkey);
650 xfree (crypto->sigkey);
651 crypto->sigkey = NULL;
652 if (new_signers)
654 crypto->sigkey = str_dup (*new_signers);
655 strv_free (new_signers);
656 crypto_keyid_to_16b_once (crypto->sigkey);
662 if (rc)
664 strv_free (new_recipients);
665 strv_free (new_signers);
668 pthread_cleanup_pop (1); // free_gpgme_data_cb (plain)
669 return rc;
672 void
673 crypto_free_key_list (gpgme_key_t *keys)
675 int i;
677 for (i = 0; keys && keys[i]; i++)
678 gpgme_key_unref (keys[i]);
680 xfree (keys);
683 /* Removes strings in 'prune' from 'a'. */
684 static char **
685 prune_keys (char **a, char **prune)
687 char **p;
689 for (p = prune; p && *p; p++)
691 char **ap;
693 for (ap = a; ap && *ap; ap++)
695 if (!strcmp (*ap, *p))
697 while (*ap)
699 *ap = *(ap+1);
700 ap++;
706 return a;
709 static void
710 remove_duplicates (char **a)
712 char **p;
714 for (p = a; p && *p; p++)
716 char **t;
718 for (t = p+1; t && *t; t++)
720 if (!strcmp (*p, *t))
722 char *tmp = *t;
724 while (*(t+1))
726 *t = *(t+1);
727 t++;
730 *t = NULL;
731 xfree (tmp);
732 remove_duplicates (a);
733 return;
739 gpgme_error_t
740 crypto_encrypt (struct client_s *client, struct crypto_s *crypto)
742 gpgme_error_t rc;
743 gpgme_data_t cipher = NULL;
744 gpgme_key_t *keys = NULL;
745 gpgme_key_t *sigkeys = NULL;
746 unsigned flags = 0;
747 int sign = 0;
749 if (!(crypto->flags & CRYPTO_FLAG_SYMMETRIC))
751 crypto_keyid_to_16b (crypto->save.pubkey);
752 remove_duplicates (crypto->save.pubkey);
753 rc = crypto_list_keys (crypto, crypto->save.pubkey, 0, &keys);
754 if (rc)
755 return rc;
758 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
759 rc = gpgme_data_new (&cipher);
760 pthread_cleanup_push ((void *)free_gpgme_data_cb, cipher);
761 if (!rc)
762 rc = gpgme_data_set_file_name (cipher, crypto->filename);
764 if (!rc && crypto->save.sigkey)
766 char **tmp = NULL;
768 crypto_keyid_to_16b_once (crypto->save.sigkey);
769 strv_printf (&tmp, "%s", crypto->save.sigkey);
770 pthread_cleanup_push ((void *)strv_free, tmp);
771 rc = crypto_list_keys (crypto, tmp, 1, &sigkeys);
772 pthread_cleanup_pop (1);
773 if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
774 rc = 0;
777 if (!rc)
779 gpgme_data_t plain = NULL;
781 pthread_cleanup_push ((void *)crypto_free_key_list, sigkeys);
782 rc = gpgme_data_new_from_mem (&plain, (char *)crypto->plaintext,
783 crypto->plaintext_size, 0);
784 pthread_cleanup_push ((void *)free_gpgme_data_cb, plain);
785 if (!rc)
787 int i;
789 gpgme_signers_clear (crypto->ctx);
791 for (i = 0; sigkeys && sigkeys[i]; i++)
792 gpgme_signers_add (crypto->ctx, sigkeys[i]);
795 if (!rc)
797 gpgme_data_set_encoding (cipher, GPGME_DATA_ENCODING_ARMOR);
798 rc = send_status (client ? client->ctx : NULL, STATUS_ENCRYPT, NULL);
801 if (!rc)
803 int f = config_get_boolean ("global", "encrypt_to");
805 if (!f)
806 flags |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
808 f = config_get_boolean ("global", "always_trust");
809 if (f)
810 flags |= GPGME_ENCRYPT_ALWAYS_TRUST;
812 if (!(crypto->flags & CRYPTO_FLAG_SYMMETRIC)
813 || (crypto->flags & CRYPTO_FLAG_SYMMETRIC && sigkeys))
814 sign = 1;
817 if (!rc)
818 MUTEX_TRYLOCK (client->ctx, &crypto_mutex, rc, client->lock_timeout);
820 if (!rc)
822 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
823 if (sign)
824 rc = gpgme_op_encrypt_sign_start (crypto->ctx, keys, flags, plain,
825 cipher);
826 else
827 rc = gpgme_op_encrypt_start (crypto->ctx, NULL, flags, plain,
828 cipher);
829 if (!rc)
831 STATUS_TIMEOUT_INIT (crypto);
834 if (!rc && crypto->progress_rc)
835 rc = crypto->progress_rc;
836 if (!rc)
837 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_ENCRYPT, NULL);
838 TEST_CANCEL();
839 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
841 pthread_cleanup_pop (1);
843 if (!rc)
845 gpgme_encrypt_result_t result;
846 gpgme_sign_result_t sresult;
847 gpgme_invalid_key_t inv;
848 gpgme_new_signature_t sigs;
849 char **prune = NULL;
850 char **p = NULL;
852 result = gpgme_op_encrypt_result (crypto->ctx);
853 inv = result->invalid_recipients;
854 while (inv)
856 pthread_cleanup_push ((void *)strv_free, prune);
857 log_write1 (_ ("%s: invalid recipient: %s, rc=%u"),
858 crypto->filename, inv->fpr, inv->reason);
859 pthread_cleanup_pop (0);
860 p = strv_cat (prune, str_dup(inv->fpr));
861 if (!p)
863 rc = GPG_ERR_ENOMEM;
864 strv_free (prune);
865 break;
868 prune = p;
869 inv = inv->next;
872 if (prune)
874 p = prune_keys (crypto->save.pubkey, prune);
875 crypto->save.pubkey = p;
876 strv_free (prune);
879 crypto_keyid_to_16b (crypto->save.pubkey);
880 sresult = gpgme_op_sign_result (crypto->ctx);
881 inv = sresult ? sresult->invalid_signers : NULL;
882 while (!rc && inv)
884 log_write1 (_ ("%s: invalid signer: %s, rc=%u"),
885 crypto->filename, inv->fpr, inv->reason);
886 inv = inv->next;
889 sigs = sresult ? sresult->signatures : NULL;
890 if (!rc && sigs)
892 p = NULL;
894 while (sigs)
896 char **pp;
898 pthread_cleanup_push ((void *)strv_free, p);
899 log_write1 (_ ("%s: signer: %s"), crypto->filename,
900 sigs->fpr);
901 pthread_cleanup_pop (0);
903 pp = strv_cat (p, str_dup (sigs->fpr));
904 if (!pp)
906 rc = GPG_ERR_ENOMEM;
907 strv_free (p);
908 break;
911 p = pp;
912 sigs = sigs->next;
915 if (!rc)
917 xfree (crypto->save.sigkey);
918 crypto->save.sigkey = str_dup (*p);
919 strv_free (p);
920 crypto_keyid_to_16b_once (crypto->save.sigkey);
921 crypto->cipher = cipher;
924 else if (!rc && crypto->flags & CRYPTO_FLAG_SYMMETRIC)
926 crypto->cipher = cipher;
928 else if (!rc)
930 if (!(crypto->flags & CRYPTO_FLAG_SYMMETRIC)
931 || (crypto->flags & CRYPTO_FLAG_SYMMETRIC && sigkeys))
932 rc = GPG_ERR_NO_SIGNATURE_SCHEME;
937 pthread_cleanup_pop (1); // free_gpgme_data_cb (plain)
938 pthread_cleanup_pop (1); // crypto_free_key_list (sigkeys)
941 pthread_cleanup_pop (0); // free_gpgme_data_cb (cipher)
942 pthread_cleanup_pop (1); // crypto_free_key_list (keys)
944 if (rc)
945 free_gpgme_data_cb (cipher);
947 return rc;
950 gpgme_error_t
951 crypto_passwd (struct client_s *client, struct crypto_s *crypto)
953 gpgme_error_t rc;
954 gpgme_key_t *keys = NULL;
956 /* Use SAVE instead for symmetric files. */
957 rc = crypto_is_symmetric (client->filename);
958 if (!rc || rc != GPG_ERR_BAD_DATA)
959 return !rc ? GPG_ERR_NOT_SUPPORTED : rc;
961 /* Cannot change the passphrase of a key stored on a smartcard. Use
962 * gpg --card-edit instead. */
963 rc = cache_is_shadowed (client->filename);
964 if (!rc)
965 return GPG_ERR_NOT_SUPPORTED;
966 else if (rc != GPG_ERR_NO_DATA)
967 return rc;
969 rc = crypto_list_keys (crypto, crypto->pubkey, 1, &keys);
970 if (rc)
971 return rc;
973 crypto->flags |= CRYPTO_FLAG_PASSWD;
974 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
975 rc = send_status (client->ctx, STATUS_KEEPALIVE, NULL);
976 if (!rc)
977 MUTEX_TRYLOCK (client->ctx, &crypto_mutex, rc, client->lock_timeout);
979 if (!rc)
981 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
982 rc = gpgme_op_passwd_start (crypto->ctx, keys[0], 0);
983 if (!rc)
985 STATUS_TIMEOUT_INIT (crypto);
988 if (!rc && crypto->progress_rc)
989 rc = crypto->progress_rc;
990 if (!rc)
991 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_KEEPALIVE, NULL);
992 TEST_CANCEL();
993 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
995 pthread_cleanup_pop (1);
998 pthread_cleanup_pop (1);
999 return rc;
1002 /* Generate a new key pair. The resulting keyid's are stored in crypto->save.
1004 gpgme_error_t
1005 crypto_genkey (struct client_s *client, struct crypto_s *crypto)
1007 gpgme_error_t rc;
1009 rc = send_status (client ? client->ctx : NULL, STATUS_GENKEY, NULL);
1010 if (!rc)
1011 MUTEX_TRYLOCK ((client ? client->ctx : NULL), &crypto_mutex, rc,
1012 (client ? client->lock_timeout : 0));
1014 if (!rc)
1016 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
1017 if (crypto->save.mainkey)
1019 rc = gpgme_op_createsubkey_start (crypto->ctx,
1020 crypto->save.mainkey[0],
1021 crypto->save.algo,
1023 crypto->save.expire,
1024 crypto->save.flags);
1026 else
1028 rc = gpgme_op_createkey_start (crypto->ctx,
1029 crypto->save.userid,
1030 crypto->save.algo,
1032 crypto->save.expire,
1033 NULL,
1034 crypto->save.flags);
1037 if (!rc)
1039 STATUS_TIMEOUT_INIT (crypto);
1042 if (!rc && crypto->progress_rc)
1043 rc = crypto->progress_rc;
1044 if (!rc)
1045 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_GENKEY, NULL);
1046 TEST_CANCEL();
1047 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
1049 pthread_cleanup_pop (1);
1052 if (!rc)
1054 gpgme_key_t *keys = NULL;
1055 gpgme_genkey_result_t result;
1057 result = gpgme_op_genkey_result (crypto->ctx);
1058 xfree (crypto->save.sigkey);
1059 crypto->save.sigkey = str_dup (result->fpr);
1060 crypto_keyid_to_16b_once (crypto->save.sigkey);
1062 if (!rc)
1064 char **tmp = NULL;
1066 strv_printf (&tmp, "%s", crypto->save.sigkey);
1067 pthread_cleanup_push ((void *)strv_free, tmp);
1068 rc = crypto_list_keys (crypto, tmp, 1, &keys);
1069 pthread_cleanup_pop (1);
1072 if (!rc)
1074 gpgme_subkey_t key = keys[0]->subkeys;
1076 for (; key; key = key->next)
1078 if (key->can_encrypt)
1079 break;
1082 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
1083 rc = send_status (client ? client->ctx : NULL, STATUS_GENKEY, "%s %s",
1084 crypto->save.sigkey, key ? key->fpr : "");
1085 if (!rc && key)
1087 crypto->save.pubkey = strv_cat (crypto->save.pubkey,
1088 str_dup (key->fpr));
1089 crypto_keyid_to_16b (crypto->save.pubkey);
1092 pthread_cleanup_pop (1);
1096 return rc;
1099 #ifdef WITH_LIBACL
1100 static void
1101 acl_free_cb (void *arg)
1103 acl_t acl = arg ? (acl_t) arg : NULL;
1105 if (acl)
1106 acl_free (acl);
1108 #endif
1110 /* The advisory lock should be obtained before calling this function. */
1111 gpg_error_t
1112 crypto_write_file (struct crypto_s *crypto, unsigned char **r_crc,
1113 size_t *r_crclen)
1115 unsigned char *buf;
1116 size_t size, len;
1117 int fd;
1118 gpg_error_t rc;
1119 char tmp[PATH_MAX];
1120 struct stat st;
1121 mode_t mode = 0600;
1122 #ifdef WITH_LIBACL
1123 acl_t acl = NULL;
1124 #endif
1126 if (crypto->filename)
1128 if (lstat (crypto->filename, &st) == 0)
1130 mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
1132 if (!(mode & S_IWUSR))
1133 return GPG_ERR_EACCES;
1135 else if (errno != ENOENT)
1136 return gpg_error_from_errno (errno);
1138 snprintf (tmp, sizeof (tmp), "%s.XXXXXX", crypto->filename);
1139 mode_t tmode = umask (0600);
1140 fd = mkstemp (tmp);
1141 if (fd == -1)
1143 rc = gpg_error_from_errno (errno);
1144 umask (tmode);
1145 log_write ("%s: %s", tmp, pwmd_strerror (rc));
1146 return rc;
1149 umask (tmode);
1151 else
1152 fd = STDOUT_FILENO;
1154 rc = crypto_data_to_buf (crypto->cipher, &buf, &size);
1155 if (rc)
1157 if (crypto->filename)
1158 close (fd);
1159 return rc;
1162 pthread_cleanup_push ((void *)close_fd_cb, &fd);
1163 if (r_crc)
1164 rc = get_checksum_memory (buf, size, r_crc, r_crclen);
1166 if (!rc)
1168 pthread_cleanup_push ((void *)xfree, buf);
1169 len = write (fd, buf, size);
1170 pthread_cleanup_pop (1);
1171 if (len != size)
1172 rc = gpg_error_from_errno (errno);
1175 if (!rc)
1177 if (fsync (fd) != -1)
1179 if (crypto->filename && close (fd) != -1)
1181 #ifdef WITH_LIBACL
1182 acl = acl_get_file (crypto->filename, ACL_TYPE_ACCESS);
1183 if (!acl && errno == ENOENT)
1184 acl = acl_get_file (".", ACL_TYPE_DEFAULT);
1185 if (!acl)
1186 log_write ("ACL: %s: %s", crypto->filename,
1187 pwmd_strerror (gpg_error_from_errno (errno)));
1188 pthread_cleanup_push ((void *)acl_free_cb, acl);
1189 #endif
1191 fd = -1;
1192 if (config_get_boolean (crypto->filename, "backup"))
1194 char tmp2[PATH_MAX];
1196 snprintf (tmp2, sizeof (tmp2), "%s.backup", crypto->filename);
1197 if (rename (crypto->filename, tmp2) == -1)
1198 if (errno != ENOENT)
1199 rc = gpg_error_from_errno (errno);
1202 if (!rc && rename (tmp, crypto->filename) == -1)
1203 rc = gpg_error_from_errno (errno);
1205 if (!rc)
1207 if (chmod (crypto->filename, mode) == -1)
1208 log_write ("%s(%u): %s", __FILE__, __LINE__,
1209 pwmd_strerror (gpg_error_from_syserror ()));
1211 #ifdef WITH_LIBACL
1212 if (!rc && acl && acl_set_file (crypto->filename,
1213 ACL_TYPE_ACCESS, acl))
1214 log_write ("ACL: %s: %s", crypto->filename,
1215 pwmd_strerror (gpg_error_from_errno (errno)));
1216 pthread_cleanup_pop (1);
1217 #endif
1219 else if (crypto->filename)
1220 rc = gpg_error_from_errno (errno);
1222 if (!rc && fd != -1)
1224 char *datadir = str_asprintf ("%s/data", homedir);
1226 if (datadir)
1228 int dfd = open (datadir, O_RDONLY);
1230 if (dfd != -1)
1232 if (fsync (dfd) == -1)
1233 log_write ("%s %d: %s", __FILE__, __LINE__,
1234 pwmd_strerror (errno));
1236 close (dfd);
1238 else
1239 log_write ("%s %d: %s", __FILE__, __LINE__,
1240 pwmd_strerror (errno));
1242 xfree (datadir);
1246 else
1247 rc = gpg_error_from_errno (errno);
1250 pthread_cleanup_pop (0); // close (fd)
1251 if (fd != -1)
1252 close (fd);
1254 return rc;
1257 char *
1258 crypto_key_info (const gpgme_key_t key)
1260 struct string_s *string = string_new (NULL), *s;
1261 char *line = NULL;
1262 unsigned n, u;
1263 gpgme_subkey_t subkey;
1264 gpgme_user_id_t uid;
1266 if (!string)
1267 return NULL;
1269 for (u = 0, uid = key->uids; uid; uid = uid->next)
1270 u++;
1272 for (n = 0, subkey = key->subkeys; subkey; subkey = subkey->next)
1273 n++;
1275 s = string_append_printf (string, "%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%i:%s:%s:%s:%i:%u:%u",
1276 key->revoked, key->expired, key->disabled,
1277 key->invalid, key->can_encrypt, key->can_sign,
1278 key->can_certify, key->secret,
1279 key->can_authenticate, key->is_qualified,
1280 key->protocol,
1281 key->issuer_serial ? key->issuer_serial : "",
1282 key->issuer_name ? key->issuer_name : "",
1283 key->chain_id ? key->chain_id : "",
1284 key->owner_trust, u, n);
1285 if (!s)
1287 string_free (string, 1);
1288 return NULL;
1291 string = s;
1292 for (subkey = key->subkeys; subkey; subkey = subkey->next)
1294 char *tmp;
1296 s = string_append_printf (string, ":%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%i:%u",
1297 subkey->revoked, subkey->expired,
1298 subkey->disabled, subkey->invalid,
1299 subkey->can_encrypt, subkey->can_sign,
1300 subkey->can_certify, subkey->secret,
1301 subkey->can_authenticate, subkey->is_qualified,
1302 subkey->is_cardkey, subkey->pubkey_algo,
1303 subkey->length);
1304 if (!s)
1306 string_free (string, 1);
1307 return NULL;
1310 string = s;
1311 s = string_append_printf (string, ":%s:%s:%s:%li:%li:%s",
1312 subkey->keyid, subkey->fpr,
1313 subkey->keygrip ? subkey->keygrip : "",
1314 subkey->timestamp, subkey->expires,
1315 subkey->card_number ? subkey->card_number : "0");
1316 if (!s)
1318 string_free (string, 1);
1319 return NULL;
1322 string = s;
1323 tmp = gnupg_escape (subkey->curve);
1324 s = string_append_printf (string, ":%s", tmp ? tmp : "");
1325 xfree (tmp);
1326 if (!s)
1328 string_free (string, 1);
1329 return NULL;
1332 string = s;
1335 for (uid = key->uids; uid; uid = uid->next)
1337 char *userid, *name, *email, *comment;
1339 userid = gnupg_escape (uid->uid);
1340 name = gnupg_escape (uid->name);
1341 email = gnupg_escape (uid->email);
1342 comment = gnupg_escape (uid->comment);
1343 s = string_append_printf (string, ":%u:%u:%u:%s:%s:%s:%s",
1344 uid->revoked, uid->invalid, uid->validity,
1345 userid ? userid : "",
1346 name ? name : "",
1347 email ? email : "",
1348 comment ? comment : "");
1349 xfree (userid);
1350 xfree (name);
1351 xfree (email);
1352 xfree (comment);
1353 if (!s)
1355 string_free (string, 1);
1356 return NULL;
1359 string = s;
1362 line = string->str;
1363 string_free (string, 0);
1364 return line;
1367 gpg_error_t
1368 crypto_try_decrypt (struct client_s *client, int no_pinentry)
1370 struct crypto_s *crypto;
1371 gpg_error_t rc;
1372 char *keyfile = config_get_string (client->filename, "passphrase_file");
1374 rc = crypto_init (&crypto, client->ctx, client->filename, no_pinentry,
1375 keyfile);
1376 if (!rc)
1378 pthread_cleanup_push ((void *)crypto_free, crypto);
1379 rc = crypto_decrypt (client, crypto);
1380 pthread_cleanup_pop (1);
1382 else
1383 xfree (keyfile);
1385 return rc;
1388 /* The advisory lock should be obtained before calling this function. */
1389 gpg_error_t
1390 crypto_is_symmetric (const char *filename)
1392 int fd;
1393 uint8_t magic[2];
1394 ssize_t len;
1395 gpg_error_t rc;
1397 rc = open_check_file (filename, &fd, NULL, 1);
1398 if (rc)
1399 return rc;
1401 len = read (fd, &magic, sizeof(magic));
1402 close (fd);
1403 if (len != sizeof (magic))
1404 return GPG_ERR_INV_VALUE;
1406 // Always read as big endian.
1407 if (magic[0] != 0x8c || magic[1] != 0x0d)
1408 return GPG_ERR_BAD_DATA;
1410 return 0;
1413 gpg_error_t
1414 crypto_delete_key (struct client_s *client, struct crypto_s *crypto,
1415 const gpgme_key_t key, int secret)
1417 gpg_error_t rc;
1419 STATUS_TIMEOUT_INIT (crypto);
1420 rc = send_status (client->ctx, STATUS_DECRYPT, NULL);
1421 if (!rc)
1422 rc = gpgme_op_delete_ext_start (crypto->ctx, key, GPGME_DELETE_FORCE
1423 | GPGME_DELETE_ALLOW_SECRET);
1425 if (rc)
1426 return rc;
1430 if (!rc && crypto->progress_rc)
1431 rc = crypto->progress_rc;
1433 if (!rc)
1434 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_DECRYPT, NULL);
1436 if (rc)
1437 break;
1438 } while (!gpgme_wait (crypto->ctx, &rc, 0) && !rc);
1440 return rc;