Reset signal_thread_key upon cancellation.
[libpwmd.git] / src / crypto.c
blob8f844d7f35964cce2b56c06ba69fa169b91465fe
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015,
3 2016
4 Ben Kibbey <bjk@luxsci.net>
6 This file is part of pwmd.
8 Pwmd is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
13 Pwmd is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
25 #include <stdio.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <errno.h>
31 #ifdef WITH_LIBACL
32 #include <sys/acl.h>
33 #endif
35 #include "pwmd-error.h"
36 #include "util-misc.h"
37 #include "common.h"
38 #include "rcfile.h"
39 #include "crypto.h"
40 #include "cache.h"
41 #include "mem.h"
42 #include "util-string.h"
43 #include "rcfile.h"
44 #include "mutex.h"
46 static int keepalive;
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 #if 0
66 static gpgme_error_t
67 show_key_output (gpgme_key_t key)
69 gpgme_subkey_t keyp; // first is primary
71 for (keyp = key->subkeys; keyp; keyp = keyp->next)
73 fprintf(stderr, "keyid: %s, revoked: %i, expired: %i, disabled: %i, invalid: %i,"
74 "encrypt: %i, sign: %i, cert: %i, auth: %i, secret: %i\n",
75 keyp->keyid, keyp->revoked, keyp->expired, keyp->disabled,
76 keyp->invalid, keyp->can_encrypt, keyp->can_sign,
77 keyp->can_certify, keyp->can_authenticate, keyp->secret);
80 return 0;
82 #endif
84 static gpg_error_t
85 get_password (const char *keyfile, unsigned char **result, size_t *len)
87 struct stat st;
88 int fd;
89 unsigned char *buf = NULL;
90 gpg_error_t rc = 0;
92 log_write (_ ("obtaining passphrase from passphrase file"));
93 if (stat (keyfile, &st) == -1)
94 return gpg_error_from_syserror ();
96 fd = open (keyfile, O_RDONLY);
97 if (fd == -1)
98 return gpg_error_from_syserror ();
100 buf = xmalloc (st.st_size+1);
101 if (buf)
103 size_t rlen = read (fd, buf, st.st_size);
105 if (rlen != st.st_size)
106 rc = GPG_ERR_ASS_READ_ERROR;
107 else
109 buf[rlen] = 0;
110 if (rlen && strlen ((char *)buf) != rlen)
111 rc = GPG_ERR_INV_PASSPHRASE;
113 if (!rc)
115 *result = buf;
116 *len = rlen;
120 else
121 rc = GPG_ERR_ENOMEM;
123 close (fd);
124 if (rc)
125 xfree (buf);
127 return rc;
130 static gpgme_error_t
131 status_cb (void *data, const char *keyword, const char *args)
133 struct crypto_s *crypto = data;
135 // Cache pushing.
136 if (!crypto->client_ctx)
137 return 0;
139 if (!strcmp (keyword, "INQUIRE_MAXLEN") &&
140 (crypto->flags & CRYPTO_FLAG_KEYFILE))
141 return 0;
143 return assuan_write_status (crypto->client_ctx, keyword, args);
146 static gpgme_error_t
147 passphrase_cb (void *data, const char *hint, const char *info, int bad, int fd)
149 struct crypto_s *crypto = data;
150 unsigned char *result = NULL;
151 size_t len;
152 gpg_error_t rc = 0;
154 if (crypto->flags & CRYPTO_FLAG_KEYFILE)
155 rc = get_password (crypto->keyfile, &result, &len);
156 else
158 if (hint)
159 rc = assuan_write_status (crypto->client_ctx, "PASSPHRASE_HINT", hint);
161 if (!rc && info)
162 rc = assuan_write_status (crypto->client_ctx, "PASSPHRASE_INFO", info);
164 if (!rc)
166 char *keyword = "PASSPHRASE";
168 /* FIXME: how to handle multiple signers */
169 if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD_SIGN)
170 keyword = "SIGN_PASSPHRASE";
171 else if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD_NEW)
173 crypto->flags |= CRYPTO_FLAG_PASSWD_SIGN;
174 keyword = "NEW_PASSPHRASE";
176 else if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD)
177 crypto->flags |= CRYPTO_FLAG_PASSWD_NEW;
178 else if (!bad && crypto->flags & CRYPTO_FLAG_NEWFILE)
180 keyword = "NEW_PASSPHRASE";
181 if (crypto->save.sigkey)
182 crypto->flags |= CRYPTO_FLAG_PASSWD_SIGN;
185 rc = assuan_inquire (crypto->client_ctx, keyword, &result, &len, 0);
189 if (!rc)
191 pthread_cleanup_push ((void *)xfree, result);
193 if (!len)
194 gpgme_io_writen (fd, "\n", 1);
195 else
197 int nl = result[len-1] == '\n';
198 int ret;
200 ret = gpgme_io_writen (fd, result, len);
201 if (!ret && !nl)
202 gpgme_io_writen (fd, "\n", 1);
203 else if (ret)
204 rc = GPG_ERR_CANCELED;
207 pthread_cleanup_pop (1);
210 return rc;
213 static void
214 progress_cb (void *data, const char *what, int type, int current, int total)
216 struct crypto_s *crypto = data;
218 crypto->progress_rc = send_status (crypto->client_ctx, STATUS_GPGME,
219 "%s %i %i %i", what, type, current, total);
222 gpgme_error_t
223 crypto_data_to_buf (const gpgme_data_t data, unsigned char **result,
224 size_t *rlen)
226 off_t ret = gpgme_data_seek (data, 0, SEEK_SET);
227 gpgme_error_t rc;
228 size_t total = 0, size = BUFSIZE;
229 unsigned char *buf;
231 if (ret == -1)
232 return gpg_error_from_syserror ();
234 buf = xmalloc (size);
235 if (!buf)
236 return GPG_ERR_ENOMEM;
240 pthread_cleanup_push ((void *)xfree, buf);
241 ret = gpgme_data_read (data, &buf[total], BUFSIZE);
242 pthread_cleanup_pop (0);
243 if (ret > 0)
245 unsigned char *p;
247 total += ret;
248 size += BUFSIZE;
249 p = xrealloc (buf, size * sizeof(char));
250 if (!p)
252 xfree (buf);
253 return GPG_ERR_ENOMEM;
256 buf = p;
258 } while (ret > 0);
260 if (ret == -1)
262 rc = gpgme_err_code_from_syserror ();
263 xfree (buf);
264 return rc;
267 *result = buf;
268 *rlen = total;
269 return 0;
272 gpgme_error_t
273 crypto_list_keys (struct crypto_s *crypto, char *keys[], int secret,
274 gpgme_key_t **result)
276 gpgme_error_t rc;
277 gpgme_key_t key = NULL, *res = NULL;
278 size_t total = 0;
280 STATUS_TIMEOUT_INIT (crypto);
281 rc = gpgme_op_keylist_ext_start (crypto->ctx, (const char **)keys, secret, 0);
282 if (rc)
283 return rc;
287 gpgme_key_t *p;
289 pthread_cleanup_push ((void *)crypto_free_key_list, res);
290 rc = gpgme_op_keylist_next (crypto->ctx, &key);
291 pthread_cleanup_pop (0);
292 if (rc && gpgme_err_code(rc) != GPG_ERR_EOF)
293 break;
295 if (rc)
297 rc = 0;
298 break;
301 p = xrealloc (res, (total+2) * sizeof (gpgme_key_t));
302 if (!p)
304 rc = GPG_ERR_ENOMEM;
305 break;
308 res = p;
309 res[total++] = key;
310 res[total] = NULL;
311 pthread_cleanup_push ((void *)crypto_free_key_list, res);
312 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_KEEPALIVE, NULL);
313 pthread_cleanup_pop (0);
314 } while (!rc);
316 if (!rc)
318 rc = gpgme_op_keylist_end (crypto->ctx);
319 if (!rc)
321 *result = res;
322 rc = total ? 0 : secret ? GPG_ERR_NO_SECKEY : GPG_ERR_NO_PUBKEY;
325 else
326 crypto_free_key_list (res);
328 return rc;
331 void
332 crypto_free_save (struct save_s *save)
334 if (!save)
335 return;
337 strv_free (save->pubkey);
338 strv_free (save->sigkey);
339 memset (save, 0, sizeof (struct save_s));
342 static gpg_error_t
343 crypto_kill_scd ()
345 return cache_kill_scd ();
348 static void
349 free_gpgme_data_cb (void *data)
351 gpgme_data_t d = data;
352 char *t;
353 size_t len;
355 if (!data)
356 return;
358 t = gpgme_data_release_and_get_mem (d, &len);
359 if (t)
360 wipememory (t, 0, len);
362 gpgme_free (t);
365 void
366 crypto_free_non_keys (struct crypto_s *crypto)
368 if (!crypto)
369 return;
371 if (crypto->ctx)
372 gpgme_release (crypto->ctx);
374 crypto->ctx = NULL;
375 xfree (crypto->plaintext);
376 crypto->plaintext = NULL;
377 crypto->plaintext_size = 0;
379 if (crypto->cipher)
380 free_gpgme_data_cb (crypto->cipher);
382 crypto->cipher = NULL;
383 crypto_free_save (&crypto->save);
384 xfree (crypto->keyfile);
385 crypto->keyfile = NULL;
386 crypto->flags &= ~CRYPTO_FLAG_KEYFILE;
387 (void)crypto_kill_scd ();
390 void
391 crypto_free (struct crypto_s *crypto)
393 if (!crypto)
394 return;
396 crypto_free_non_keys (crypto);
397 strv_free (crypto->pubkey);
398 strv_free (crypto->sigkey);
399 xfree (crypto->filename);
400 xfree (crypto);
403 gpgme_error_t
404 crypto_init_ctx (struct crypto_s *crypto, int no_pinentry,
405 char *passphrase_file)
407 gpgme_ctx_t ctx;
408 gpgme_keylist_mode_t keylist_mode;
409 gpgme_error_t rc;
411 rc = gpgme_new (&ctx);
412 if (rc)
413 return rc;
415 rc = gpgme_set_protocol (ctx, GPGME_PROTOCOL_OPENPGP);
416 if (!rc)
418 keylist_mode = gpgme_get_keylist_mode (ctx);
419 keylist_mode |= GPGME_KEYLIST_MODE_LOCAL|GPGME_KEYLIST_MODE_WITH_SECRET;
420 rc = gpgme_set_keylist_mode (ctx, keylist_mode);
421 if (!rc)
423 if (no_pinentry || passphrase_file)
424 rc = gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_LOOPBACK);
425 else
426 rc = gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_DEFAULT);
428 if (!rc)
430 gpgme_set_passphrase_cb (ctx, passphrase_cb, crypto);
431 gpgme_set_progress_cb (ctx, progress_cb, crypto);
432 gpgme_set_status_cb (ctx, status_cb, crypto);
433 crypto->ctx = ctx;
434 crypto->flags = 0;
437 if (passphrase_file)
439 crypto->keyfile = passphrase_file;
440 crypto->flags |= CRYPTO_FLAG_KEYFILE;
445 if (rc)
446 gpgme_release (ctx);
448 return rc;
451 void
452 crypto_set_keepalive ()
454 keepalive = config_get_integer ("global", "keepalive_interval");
457 gpg_error_t
458 crypto_init (struct crypto_s **crypto, void *ctx, const char *filename,
459 int no_pinentry, char *passphrase_file)
461 struct crypto_s *new = xcalloc (1, sizeof (struct crypto_s));
462 gpgme_error_t rc;
464 crypto_set_keepalive ();
466 if (!new)
467 return GPG_ERR_ENOMEM;
469 rc = crypto_init_ctx (new, no_pinentry, passphrase_file);
470 if (rc)
471 goto fail;
473 if (filename)
475 new->filename = str_dup (filename);
476 if (!new->filename)
478 rc = GPG_ERR_ENOMEM;
479 goto fail;
483 new->client_ctx = ctx;
484 *crypto = new;
485 return 0;
487 fail:
488 crypto_free (new);
489 return rc;
492 /* Converts a 40 byte key id to the 16 byte form. Needed for comparison of
493 * gpgme_recipient_t.keyid. */
494 gpg_error_t
495 crypto_keyid_to_16b (char **keys)
497 char **p;
499 for (p = keys; p && *p; p++)
501 char *t = *p;
502 size_t len = strlen (t);
504 if (len < 16)
505 return GPG_ERR_INV_ARG;
507 memmove (&t[0], &t[len-16], 16);
508 t[16] = 0;
511 return 0;
514 gpgme_error_t
515 crypto_decrypt (struct client_s *client, struct crypto_s *crypto)
517 gpgme_data_t plain;
518 gpgme_error_t rc;
519 gpgme_data_t cipher;
520 int fd;
521 char **new_recipients = NULL;
522 char **new_signers = NULL;
523 char **pp;
524 gpgme_decrypt_result_t result;
526 rc = gpgme_data_new (&plain);
527 if (rc)
528 return rc;
530 pthread_cleanup_push ((void *)free_gpgme_data_cb, plain);
531 fd = open (crypto->filename, O_RDONLY);
532 if (fd != -1)
534 pthread_cleanup_push ((void *)close_fd_cb, &fd);
535 rc = gpgme_data_new_from_fd (&cipher, fd);
536 if (!rc)
538 pthread_cleanup_push ((void *)free_gpgme_data_cb, cipher);
539 STATUS_TIMEOUT_INIT(crypto);
540 rc = send_status (client ? client->ctx : NULL, STATUS_DECRYPT, NULL);
541 if (!rc)
542 rc = gpgme_op_decrypt_verify_start (crypto->ctx, cipher, plain);
544 if (!rc)
548 if (!rc && crypto->progress_rc)
549 rc = crypto->progress_rc;
551 if (!rc)
552 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_DECRYPT, NULL);
554 if (rc)
555 break;
556 TEST_CANCEL ();
557 } while (!gpgme_wait (crypto->ctx, &rc, 0) && !rc);
560 pthread_cleanup_pop (1); // free_gpgme_data_cb (cipher)
563 pthread_cleanup_pop (1); // close (fd)
565 else
566 rc = gpgme_err_code_from_syserror ();
568 pthread_cleanup_pop (0); // free_gpgme_data_cb (plain)
570 if (rc)
572 free_gpgme_data_cb (plain);
573 return rc;
576 pthread_cleanup_push ((void *)free_gpgme_data_cb, plain);
577 result = gpgme_op_decrypt_result (crypto->ctx);
578 if (!result->unsupported_algorithm && !result->wrong_key_usage)
580 gpgme_recipient_t r;
582 for (r = result->recipients; r; r = r->next)
584 pthread_cleanup_push ((void *)strv_free, new_recipients);
585 log_write1 (_ ("%s: recipient: %s, status=%u"),
586 crypto->filename, r->keyid, r->status);
587 pthread_cleanup_pop (0);
588 pp = strv_cat(new_recipients, str_dup (r->keyid));
589 if (!pp)
591 rc = GPG_ERR_ENOMEM;
592 break;
595 new_recipients = pp;
598 else if (result->wrong_key_usage)
599 rc = GPG_ERR_WRONG_KEY_USAGE;
600 else if (result->unsupported_algorithm)
601 rc = GPG_ERR_UNSUPPORTED_ALGORITHM;
603 if (!rc)
605 gpgme_verify_result_t result;
606 gpgme_signature_t s;
608 result = gpgme_op_verify_result (crypto->ctx);
610 for (s = result->signatures; s; s = s->next)
612 pthread_cleanup_push ((void *)strv_free, new_signers);
613 log_write1 (_ ("%s: signer: %s, status=%u"),
614 crypto->filename, s->fpr, s->status);
615 pthread_cleanup_pop (0);
616 if (s->status || s->wrong_key_usage
617 || !(s->summary & 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 (result->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);
649 strv_free (crypto->sigkey);
650 crypto->sigkey = new_signers;
651 crypto_keyid_to_16b (crypto->sigkey);
656 if (rc)
658 strv_free (new_recipients);
659 strv_free (new_signers);
662 pthread_cleanup_pop (1); // free_gpgme_data_cb (plain)
663 return rc;
666 void
667 crypto_free_key_list (gpgme_key_t *keys)
669 int i;
671 for (i = 0; keys && keys[i]; i++)
672 gpgme_key_unref (keys[i]);
674 xfree (keys);
677 /* Removes strings in 'prune' from 'a'. */
678 static char **
679 prune_keys (char **a, char **prune)
681 char **p;
683 for (p = prune; p && *p; p++)
685 char **ap;
687 for (ap = a; ap && *ap; ap++)
689 if (!strcmp (*ap, *p))
691 while (*ap)
693 *ap = *(ap+1);
694 ap++;
700 return a;
703 static void
704 remove_duplicates (char **a)
706 char **p;
708 for (p = a; p && *p; p++)
710 char **t;
712 for (t = p+1; t && *t; t++)
714 if (!strcmp (*p, *t))
716 char *tmp = *t;
718 while (*(t+1))
720 *t = *(t+1);
721 t++;
724 *t = NULL;
725 xfree (tmp);
726 remove_duplicates (a);
727 return;
733 gpgme_error_t
734 crypto_encrypt (struct client_s *client, struct crypto_s *crypto)
736 gpgme_error_t rc;
737 gpgme_data_t cipher = NULL;
738 gpgme_key_t *keys = NULL;
739 gpgme_key_t *sigkeys = NULL;
741 STATUS_TIMEOUT_INIT (crypto);
742 if (!(crypto->flags & CRYPTO_FLAG_SYMMETRIC))
744 crypto_keyid_to_16b (crypto->save.pubkey);
745 remove_duplicates (crypto->save.pubkey);
746 rc = crypto_list_keys (crypto, crypto->save.pubkey, 0, &keys);
747 if (rc)
748 return rc;
751 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
752 rc = gpgme_data_new (&cipher);
753 pthread_cleanup_push ((void *)free_gpgme_data_cb, cipher);
754 if (!rc)
755 rc = gpgme_data_set_file_name (cipher, crypto->filename);
757 if (!rc && (crypto->save.sigkey
758 || !(crypto->flags & CRYPTO_FLAG_SYMMETRIC)))
760 crypto_keyid_to_16b (crypto->save.sigkey);
761 remove_duplicates (crypto->save.sigkey);
762 rc = crypto_list_keys (crypto, crypto->save.sigkey, 1, &sigkeys);
763 if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
764 rc = 0;
767 if (!rc)
769 gpgme_data_t plain = NULL;
771 pthread_cleanup_push ((void *)crypto_free_key_list, sigkeys);
772 rc = gpgme_data_new_from_mem (&plain, (char *)crypto->plaintext,
773 crypto->plaintext_size, 0);
774 pthread_cleanup_push ((void *)free_gpgme_data_cb, plain);
775 if (!rc)
777 int i;
779 gpgme_signers_clear (crypto->ctx);
781 for (i = 0; sigkeys && sigkeys[i]; i++)
782 gpgme_signers_add (crypto->ctx, sigkeys[i]);
784 if (!i && !(crypto->flags & CRYPTO_FLAG_SYMMETRIC))
785 rc = GPG_ERR_NO_SIGNATURE_SCHEME;
788 if (!rc)
790 gpgme_data_set_encoding (cipher, GPGME_DATA_ENCODING_ARMOR);
792 rc = send_status (client ? client->ctx : NULL, STATUS_ENCRYPT, NULL);
793 if (!rc)
795 unsigned flags = 0;
796 int f = config_get_boolean ("global", "encrypt_to");
798 if (!f)
799 flags |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
801 f = config_get_boolean ("global", "always_trust");
802 if (f)
803 flags |= GPGME_ENCRYPT_ALWAYS_TRUST;
805 if (!(crypto->flags & CRYPTO_FLAG_SYMMETRIC)
806 || (crypto->flags & CRYPTO_FLAG_SYMMETRIC && sigkeys))
807 rc = gpgme_op_encrypt_sign_start (crypto->ctx,
808 (crypto->flags & CRYPTO_FLAG_SYMMETRIC) ? NULL : keys,
809 flags, plain, cipher);
810 else
811 rc = gpgme_op_encrypt_start (crypto->ctx, NULL, flags,
812 plain, cipher);
816 if (!rc)
820 if (!rc && crypto->progress_rc)
821 rc = crypto->progress_rc;
823 if (!rc)
824 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_ENCRYPT, NULL);
826 if (rc)
827 break;
828 TEST_CANCEL();
829 } while (!gpgme_wait (crypto->ctx, &rc, 0) && !rc);
831 if (!rc)
833 gpgme_encrypt_result_t result;
834 gpgme_sign_result_t sresult;
835 gpgme_invalid_key_t inv;
836 gpgme_new_signature_t sigs;
837 char **prune = NULL;
838 char **p = NULL;
840 result = gpgme_op_encrypt_result (crypto->ctx);
841 inv = result->invalid_recipients;
842 while (inv)
844 pthread_cleanup_push ((void *)strv_free, prune);
845 log_write1 (_ ("%s: invalid recipient: %s, rc=%u"),
846 crypto->filename, inv->fpr, inv->reason);
847 pthread_cleanup_pop (0);
848 p = strv_cat (prune, str_dup(inv->fpr));
849 if (!p)
851 rc = GPG_ERR_ENOMEM;
852 strv_free (prune);
853 break;
856 prune = p;
857 inv = inv->next;
860 if (prune)
862 p = prune_keys (crypto->save.pubkey, prune);
863 crypto->save.pubkey = p;
866 crypto_keyid_to_16b (crypto->save.pubkey);
867 sresult = gpgme_op_sign_result (crypto->ctx);
868 inv = sresult ? sresult->invalid_signers : NULL;
869 while (!rc && inv)
871 log_write1 (_ ("%s: invalid signer: %s, rc=%u"),
872 crypto->filename, inv->fpr, inv->reason);
873 inv = inv->next;
876 sigs = sresult ? sresult->signatures : NULL;
877 if (!rc && sigs)
879 p = NULL;
881 while (sigs)
883 char **pp;
885 pthread_cleanup_push ((void *)strv_free, p);
886 log_write1 (_ ("%s: signer: %s"), crypto->filename,
887 sigs->fpr);
888 pthread_cleanup_pop (0);
890 pp = strv_cat (p, str_dup (sigs->fpr));
891 if (!pp)
893 rc = GPG_ERR_ENOMEM;
894 strv_free (p);
895 break;
898 p = pp;
899 sigs = sigs->next;
902 if (!rc)
904 strv_free (crypto->save.sigkey);
905 crypto->save.sigkey = p;
906 crypto_keyid_to_16b (crypto->save.sigkey);
907 crypto->cipher = cipher;
910 else if (!rc && crypto->flags & CRYPTO_FLAG_SYMMETRIC)
912 crypto->cipher = cipher;
914 else if (!rc)
916 if (!(crypto->flags & CRYPTO_FLAG_SYMMETRIC)
917 || (crypto->flags & CRYPTO_FLAG_SYMMETRIC && sigkeys))
918 rc = GPG_ERR_NO_SIGNATURE_SCHEME;
923 pthread_cleanup_pop (1); // free_gpgme_data_cb (plain)
924 pthread_cleanup_pop (1); // crypto_free_key_list (sigkeys)
927 pthread_cleanup_pop (0); // free_gpgme_data_cb (cipher)
928 pthread_cleanup_pop (1); // crypto_free_key_list (keys)
930 if (rc)
931 free_gpgme_data_cb (cipher);
933 return rc;
936 gpgme_error_t
937 crypto_passwd (struct client_s *client, struct crypto_s *crypto)
939 gpgme_error_t rc;
940 gpgme_key_t *keys = NULL;
942 /* Use SAVE instead for symmetric files. */
943 rc = crypto_is_symmetric (client->filename);
944 if (!rc || rc != GPG_ERR_BAD_DATA)
945 return !rc ? GPG_ERR_NOT_SUPPORTED : rc;
947 rc = crypto_list_keys (crypto, crypto->pubkey, 1, &keys);
948 if (rc)
949 return rc;
951 crypto->flags |= CRYPTO_FLAG_PASSWD;
952 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
953 STATUS_TIMEOUT_INIT (crypto);
954 rc = send_status (client->ctx, STATUS_KEEPALIVE, NULL);
955 if (!rc)
956 rc = gpgme_op_passwd_start (crypto->ctx, keys[0], 0);
958 if (!rc)
962 if (!rc && crypto->progress_rc)
963 rc = crypto->progress_rc;
965 if (!rc)
966 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_KEEPALIVE, NULL);
968 if (rc)
969 break;
970 TEST_CANCEL();
971 } while (!gpgme_wait (crypto->ctx, &rc, 0) && !rc);
974 pthread_cleanup_pop (1);
975 return rc;
978 /* Generate a new key pair. The resulting keyid's are stored in crypto->save.
980 gpgme_error_t
981 crypto_genkey (struct client_s *client, struct crypto_s *crypto,
982 const unsigned char *params)
984 gpgme_genkey_result_t result;
985 gpgme_error_t rc;
987 if (strstr ((char *) params, "%pubring")
988 || strstr ((char *) params, "%secring"))
989 return GPG_ERR_INV_VALUE;
991 STATUS_TIMEOUT_INIT (crypto);
992 rc = send_status (client ? client->ctx : NULL, STATUS_GENKEY, NULL);
993 if (!rc)
994 rc = gpgme_op_genkey_start (crypto->ctx, (const char *)params, NULL, NULL);
996 if (rc)
997 return rc;
1001 if (!rc && crypto->progress_rc)
1002 rc = crypto->progress_rc;
1004 if (!rc)
1005 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_GENKEY, NULL);
1007 if (rc)
1008 break;
1009 TEST_CANCEL();
1010 } while (!gpgme_wait (crypto->ctx, &rc, 0) && !rc);
1012 if (!rc)
1014 gpgme_key_t *keys = NULL;
1016 result = gpgme_op_genkey_result (crypto->ctx);
1017 crypto->save.sigkey = strv_cat (crypto->save.sigkey,
1018 str_dup (result->fpr));
1019 crypto_keyid_to_16b (crypto->save.sigkey);
1021 rc = crypto_list_keys (crypto, crypto->save.sigkey, 1, &keys);
1022 if (!rc)
1024 gpgme_subkey_t key = keys[0]->subkeys;
1026 for (; key; key = key->next)
1028 if (key->can_encrypt)
1029 break;
1032 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
1033 rc = send_status (client ? client->ctx : NULL, STATUS_GENKEY, "%s %s",
1034 crypto->save.sigkey[0], key ? key->fpr : "");
1035 if (!rc)
1037 crypto->save.pubkey = strv_cat (crypto->save.pubkey,
1038 str_dup (key->fpr));
1039 crypto_keyid_to_16b (crypto->save.pubkey);
1042 pthread_cleanup_pop (1);
1046 return rc;
1049 char *
1050 crypto_default_key_params ()
1052 char *user = get_username (getuid());
1053 char *params = str_asprintf(
1054 "<GnupgKeyParms format=\"internal\">\n"
1055 " Key-Type: default\n"
1056 " Subkey-Type: default\n"
1057 " Name-Real: %s\n"
1058 " Name-Email: %s\n"
1059 " Expire-Date: 0\n"
1060 "</GnupgKeyParms>",
1061 getenv ("REALNAME") ? getenv ("REALNAME") : user,
1062 getenv ("EMAIL") ? getenv ("EMAIL") : user);
1064 xfree (user);
1065 return params;
1068 #ifdef WITH_LIBACL
1069 static void
1070 acl_free_cb (void *arg)
1072 acl_t acl = arg ? (acl_t) arg : NULL;
1074 if (acl)
1075 acl_free (acl);
1077 #endif
1079 /* The advisory lock should be obtained before calling this function. */
1080 gpg_error_t
1081 crypto_write_file (struct crypto_s *crypto)
1083 unsigned char *buf;
1084 size_t size, len;
1085 int fd;
1086 gpg_error_t rc;
1087 char tmp[PATH_MAX];
1088 struct stat st;
1089 mode_t mode = 0600;
1090 #ifdef WITH_LIBACL
1091 acl_t acl = NULL;
1092 #endif
1094 if (crypto->filename)
1096 if (lstat (crypto->filename, &st) == 0)
1098 mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
1100 if (!(mode & S_IWUSR))
1101 return GPG_ERR_EACCES;
1103 else if (errno != ENOENT)
1104 return gpg_error_from_errno (errno);
1106 snprintf (tmp, sizeof (tmp), "%s.XXXXXX", crypto->filename);
1107 mode_t tmode = umask (0600);
1108 fd = mkstemp (tmp);
1109 if (fd == -1)
1111 rc = gpg_error_from_errno (errno);
1112 umask (tmode);
1113 log_write ("%s: %s", tmp, pwmd_strerror (rc));
1114 return rc;
1117 umask (tmode);
1119 else
1120 fd = STDOUT_FILENO;
1122 rc = crypto_data_to_buf (crypto->cipher, &buf, &size);
1123 if (rc)
1125 if (crypto->filename)
1126 close (fd);
1127 return rc;
1130 pthread_cleanup_push ((void *)close_fd_cb, &fd);
1131 pthread_cleanup_push ((void *)xfree, buf);
1132 len = write (fd, buf, size);
1133 pthread_cleanup_pop (1);
1134 if (len != size)
1135 rc = gpg_error_from_errno (errno);
1137 if (!rc)
1139 if (fsync (fd) != -1)
1141 if (crypto->filename && close (fd) != -1)
1143 #ifdef WITH_LIBACL
1144 acl = acl_get_file (crypto->filename, ACL_TYPE_ACCESS);
1145 if (!acl && errno == ENOENT)
1146 acl = acl_get_file (".", ACL_TYPE_DEFAULT);
1147 if (!acl)
1148 log_write ("ACL: %s: %s", crypto->filename,
1149 pwmd_strerror (gpg_error_from_errno (errno)));
1150 pthread_cleanup_push ((void *)acl_free_cb, acl);
1151 #endif
1153 fd = -1;
1154 if (config_get_boolean (crypto->filename, "backup"))
1156 char tmp2[PATH_MAX];
1158 snprintf (tmp2, sizeof (tmp2), "%s.backup", crypto->filename);
1159 if (rename (crypto->filename, tmp2) == -1)
1160 if (errno != ENOENT)
1161 rc = gpg_error_from_errno (errno);
1164 if (!rc && rename (tmp, crypto->filename) == -1)
1165 rc = gpg_error_from_errno (errno);
1167 if (!rc)
1168 chmod (crypto->filename, mode);
1169 #ifdef WITH_LIBACL
1170 if (!rc && acl && acl_set_file (crypto->filename,
1171 ACL_TYPE_ACCESS, acl))
1172 log_write ("ACL: %s: %s", crypto->filename,
1173 pwmd_strerror (gpg_error_from_errno (errno)));
1174 pthread_cleanup_pop (1);
1175 #endif
1177 else if (crypto->filename)
1178 rc = gpg_error_from_errno (errno);
1180 if (!rc && fd != -1)
1182 char *tmp = str_asprintf ("%s/data", homedir);
1184 if (tmp)
1186 int dfd = open (tmp, O_RDONLY);
1188 if (dfd != -1)
1190 if (fsync (dfd) == -1)
1191 log_write ("%s %d: %s", __FILE__, __LINE__,
1192 pwmd_strerror (errno));
1194 close (dfd);
1196 else
1197 log_write ("%s %d: %s", __FILE__, __LINE__,
1198 pwmd_strerror (errno));
1200 xfree (tmp);
1204 else
1205 rc = gpg_error_from_errno (errno);
1208 pthread_cleanup_pop (0); // close (fd)
1209 if (fd != -1)
1210 close (fd);
1211 return rc;
1214 char *
1215 crypto_key_info (const gpgme_key_t key)
1217 struct string_s *string = string_new (NULL), *s;
1218 char *line = NULL;
1219 unsigned n, u;
1220 gpgme_subkey_t subkey;
1221 gpgme_user_id_t uid;
1223 if (!string)
1224 return NULL;
1226 for (u = 0, uid = key->uids; uid; uid = uid->next)
1227 u++;
1229 for (n = 0, subkey = key->subkeys; subkey; subkey = subkey->next)
1230 n++;
1232 s = string_append_printf (string, "%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%i:%s:%s:%s:%i:%u:%u",
1233 key->revoked, key->expired, key->disabled,
1234 key->invalid, key->can_encrypt, key->can_sign,
1235 key->can_certify, key->secret,
1236 key->can_authenticate, key->is_qualified,
1237 key->protocol,
1238 key->issuer_serial ? key->issuer_serial : "",
1239 key->issuer_name ? key->issuer_name : "",
1240 key->chain_id ? key->chain_id : "",
1241 key->owner_trust, u, n);
1242 if (!s)
1244 string_free (string, 1);
1245 return NULL;
1248 string = s;
1249 for (subkey = key->subkeys; subkey; subkey = subkey->next)
1251 char *tmp;
1253 s = string_append_printf (string, ":%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%i:%u",
1254 subkey->revoked, subkey->expired,
1255 subkey->disabled, subkey->invalid,
1256 subkey->can_encrypt, subkey->can_sign,
1257 subkey->can_certify, subkey->secret,
1258 subkey->can_authenticate, subkey->is_qualified,
1259 subkey->is_cardkey, subkey->pubkey_algo,
1260 subkey->length);
1261 if (!s)
1263 string_free (string, 1);
1264 return NULL;
1267 string = s;
1268 s = string_append_printf (string, ":%s:%s:%s:%li:%li:%s",
1269 subkey->keyid, subkey->fpr,
1270 subkey->keygrip ? subkey->keygrip : "",
1271 subkey->timestamp, subkey->expires,
1272 subkey->card_number ? subkey->card_number : "0");
1273 if (!s)
1275 string_free (string, 1);
1276 return NULL;
1279 string = s;
1280 tmp = gnupg_escape (subkey->curve);
1281 s = string_append_printf (string, ":%s", tmp ? tmp : "");
1282 xfree (tmp);
1283 if (!s)
1285 string_free (string, 1);
1286 return NULL;
1289 string = s;
1292 for (uid = key->uids; uid; uid = uid->next)
1294 char *userid, *name, *email, *comment;
1296 userid = gnupg_escape (uid->uid);
1297 name = gnupg_escape (uid->name);
1298 email = gnupg_escape (uid->email);
1299 comment = gnupg_escape (uid->comment);
1300 s = string_append_printf (string, ":%u:%u:%u:%s:%s:%s:%s",
1301 uid->revoked, uid->invalid, uid->validity,
1302 userid ? userid : "",
1303 name ? name : "",
1304 email ? email : "",
1305 comment ? comment : "");
1306 xfree (userid);
1307 xfree (name);
1308 xfree (email);
1309 xfree (comment);
1310 if (!s)
1312 string_free (string, 1);
1313 return NULL;
1316 string = s;
1319 line = string->str;
1320 string_free (string, 0);
1321 return line;
1324 gpg_error_t
1325 crypto_try_decrypt (struct client_s *client, int no_pinentry)
1327 struct crypto_s *crypto;
1328 gpg_error_t rc;
1329 char *keyfile = config_get_string (client->filename, "passphrase_file");
1331 rc = crypto_init (&crypto, client->ctx, client->filename, no_pinentry,
1332 keyfile);
1333 if (!rc)
1335 pthread_cleanup_push ((void *)crypto_free, crypto);
1336 rc = crypto_decrypt (client, crypto);
1337 pthread_cleanup_pop (1);
1339 else
1340 xfree (keyfile);
1342 return rc;
1345 /* The advisory lock should be obtained before calling this function. */
1346 gpg_error_t
1347 crypto_is_symmetric (const char *filename)
1349 int fd;
1350 uint8_t magic[2];
1351 ssize_t len;
1353 fd = open (filename, O_RDONLY);
1354 if (fd == -1)
1355 return gpg_error_from_errno (errno);
1357 len = read (fd, &magic, sizeof(magic));
1358 close (fd);
1359 if (len != sizeof (magic))
1360 return GPG_ERR_INV_VALUE;
1362 // Always read as big endian.
1363 if (magic[0] != 0x8c || magic[1] != 0x0d)
1364 return GPG_ERR_BAD_DATA;
1366 return 0;