Fix previous commit.
[pwmd.git] / src / crypto.c
blob88438f338703d6ecc3d1aa39cb27619fd771d6f8
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015,
3 2016, 2017
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>
30 #include <pthread.h>
32 #ifdef WITH_LIBACL
33 #include <sys/acl.h>
34 #endif
36 #include "pwmd-error.h"
37 #include "util-misc.h"
38 #include "common.h"
39 #include "rcfile.h"
40 #include "crypto.h"
41 #include "cache.h"
42 #include "mem.h"
43 #include "util-string.h"
44 #include "rcfile.h"
45 #include "mutex.h"
47 static unsigned keepalive;
48 static pthread_mutex_t crypto_mutex = PTHREAD_MUTEX_INITIALIZER;
50 #define BUFSIZE 4096
52 #define STATUS_TIMEOUT_INIT(crypto) \
53 do { \
54 crypto->status_timeout = time (NULL); \
55 crypto->progress_rc = 0; \
56 } while (0)
58 #define STATUS_TIMEOUT_TEST(crypto, rc, s, line) \
59 do { \
60 time_t now = time (NULL); \
61 if (now - crypto->status_timeout >= keepalive && crypto->client_ctx) { \
62 rc = send_status (crypto->client_ctx, s, line); \
63 crypto->status_timeout = now; \
64 } \
65 } while (0)
67 static gpg_error_t
68 get_password_file (const char *keyfile, unsigned char **result, size_t *len)
70 struct stat st;
71 int fd;
72 unsigned char *buf = NULL;
73 gpg_error_t rc = 0;
75 log_write (_ ("obtaining passphrase from passphrase file"));
76 rc = open_check_file (keyfile, &fd, &st, 0);
77 if (rc)
78 return rc;
80 buf = xmalloc (st.st_size+1);
81 if (buf)
83 size_t rlen = read (fd, buf, st.st_size);
85 if (rlen != st.st_size)
86 rc = GPG_ERR_ASS_READ_ERROR;
87 else
89 buf[rlen] = 0;
90 /* The passphrase may have been truncated do to a nul byte before the
91 * EOF. Better to return an error here rather than passing the
92 * truncated passphrase on. */
93 if (rlen && strlen ((char *)buf) != rlen)
94 rc = GPG_ERR_INV_PASSPHRASE;
96 if (!rc)
98 *result = buf;
99 *len = rlen;
103 else
104 rc = GPG_ERR_ENOMEM;
106 close (fd);
107 if (rc)
108 xfree (buf);
110 return rc;
113 static gpgme_error_t
114 status_cb (void *data, const char *keyword, const char *args)
116 struct crypto_s *crypto = data;
118 // Cache pushing.
119 if (!crypto->client_ctx)
120 return 0;
122 if (!strcmp (keyword, "INQUIRE_MAXLEN") &&
123 (crypto->flags & CRYPTO_FLAG_KEYFILE))
124 return 0;
126 return assuan_write_status (crypto->client_ctx, keyword, args);
129 static gpgme_error_t
130 passphrase_cb (void *data, const char *hint, const char *info, int bad, int fd)
132 struct crypto_s *crypto = data;
133 unsigned char *result = NULL;
134 size_t len;
135 gpg_error_t rc = 0;
137 if (crypto->flags & CRYPTO_FLAG_KEYFILE)
138 rc = get_password_file (crypto->keyfile, &result, &len);
139 else
141 if (hint)
142 rc = assuan_write_status (crypto->client_ctx, "PASSPHRASE_HINT", hint);
144 if (!rc && info)
145 rc = assuan_write_status (crypto->client_ctx, "PASSPHRASE_INFO", info);
147 if (!rc)
149 const char *keyword = "PASSPHRASE";
151 if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD_SIGN)
152 keyword = "SIGN_PASSPHRASE";
153 else if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD_NEW)
155 crypto->flags |= CRYPTO_FLAG_PASSWD_SIGN;
156 keyword = "NEW_PASSPHRASE";
158 else if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD)
159 crypto->flags |= CRYPTO_FLAG_PASSWD_NEW;
160 else if (!bad && crypto->flags & CRYPTO_FLAG_NEWFILE)
162 keyword = "NEW_PASSPHRASE";
163 if (crypto->save.sigkey)
164 crypto->flags |= CRYPTO_FLAG_PASSWD_SIGN;
167 rc = assuan_inquire (crypto->client_ctx, keyword, &result, &len, 0);
171 if (!rc)
173 pthread_cleanup_push ((void *)xfree, result);
175 if (!len)
176 gpgme_io_writen (fd, "\n", 1);
177 else
179 int nl = result[len-1] == '\n';
180 int ret;
182 ret = gpgme_io_writen (fd, result, len);
183 if (!ret && !nl)
184 gpgme_io_writen (fd, "\n", 1);
185 else if (ret)
186 rc = GPG_ERR_CANCELED;
189 pthread_cleanup_pop (1);
192 return rc;
195 static void
196 progress_cb (void *data, const char *what, int type, int current, int total)
198 struct crypto_s *crypto = data;
200 crypto->progress_rc = send_status (crypto->client_ctx, STATUS_GPGME,
201 "%s %i %i %i", what, type, current, total);
204 gpgme_error_t
205 crypto_data_to_buf (const gpgme_data_t data, unsigned char **result,
206 size_t *rlen)
208 off_t ret = gpgme_data_seek (data, 0, SEEK_SET);
209 gpgme_error_t rc;
210 size_t total = 0, size = BUFSIZE;
211 unsigned char *buf = NULL;
213 *result = NULL;
214 *rlen = 0;
216 if (ret == -1)
217 return gpg_error_from_syserror ();
219 buf = xmalloc (size);
220 if (!buf)
221 return GPG_ERR_ENOMEM;
225 ret = gpgme_data_read (data, &buf[total], BUFSIZE);
226 if (ret > 0)
228 unsigned char *p;
230 total += ret;
231 size += BUFSIZE;
232 p = xrealloc (buf, size * sizeof (unsigned char));
233 if (!p)
235 xfree (buf);
236 return GPG_ERR_ENOMEM;
239 buf = p;
241 } while (ret > 0);
243 if (ret == -1)
245 rc = gpgme_err_code_from_syserror ();
246 xfree (buf);
247 return rc;
250 if (!total)
251 xfree (buf);
252 else
253 *result = buf;
255 *rlen = total;
256 return 0;
259 gpgme_error_t
260 crypto_list_keys (struct crypto_s *crypto, char *keys[], int secret,
261 gpgme_key_t **result)
263 gpgme_error_t rc;
264 gpgme_key_t key = NULL, *res = NULL;
265 size_t total = 0;
267 rc = gpgme_op_keylist_ext_start (crypto->ctx, (const char **)keys, secret, 0);
268 if (rc)
269 return rc;
271 STATUS_TIMEOUT_INIT (crypto);
274 gpgme_key_t *p;
276 pthread_cleanup_push ((void *)crypto_free_key_list, res);
277 rc = gpgme_op_keylist_next (crypto->ctx, &key);
278 pthread_cleanup_pop (0);
279 if (rc && gpgme_err_code(rc) != GPG_ERR_EOF)
280 break;
282 if (rc)
284 rc = 0;
285 break;
288 p = xrealloc (res, (total+2) * sizeof (gpgme_key_t));
289 if (!p)
291 rc = GPG_ERR_ENOMEM;
292 break;
295 res = p;
296 res[total++] = key;
297 res[total] = NULL;
298 pthread_cleanup_push ((void *)crypto_free_key_list, res);
299 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_KEEPALIVE, NULL);
300 pthread_cleanup_pop (0);
301 } while (!rc);
303 if (!rc)
305 rc = gpgme_op_keylist_end (crypto->ctx);
306 if (!rc)
308 *result = res;
309 rc = total ? 0 : secret ? GPG_ERR_NO_SECKEY : GPG_ERR_NO_PUBKEY;
312 else
313 crypto_free_key_list (res);
315 return rc;
318 void
319 crypto_free_save (struct save_s *save)
321 if (!save)
322 return;
324 strv_free (save->pubkey);
325 xfree (save->sigkey);
326 xfree (save->userid);
327 xfree (save->algo);
328 crypto_free_key_list (save->mainkey);
330 memset (save, 0, sizeof (struct save_s));
333 static gpg_error_t
334 crypto_kill_scd ()
336 return cache_kill_scd ();
339 static void
340 free_gpgme_data_cb (void *data)
342 gpgme_data_t d = data;
343 char *t;
344 size_t len;
346 if (!data)
347 return;
349 t = gpgme_data_release_and_get_mem (d, &len);
350 if (t)
351 wipememory (t, 0, len);
353 gpgme_free (t);
356 void
357 crypto_free_non_keys (struct crypto_s *crypto)
359 if (!crypto)
360 return;
362 if (crypto->ctx)
363 gpgme_release (crypto->ctx);
365 crypto->ctx = NULL;
366 xfree (crypto->plaintext);
367 crypto->plaintext = NULL;
368 crypto->plaintext_size = 0;
370 if (crypto->cipher)
371 free_gpgme_data_cb (crypto->cipher);
373 crypto->cipher = NULL;
374 crypto_free_save (&crypto->save);
375 xfree (crypto->keyfile);
376 crypto->keyfile = NULL;
377 crypto->flags &= ~CRYPTO_FLAG_KEYFILE;
378 (void)crypto_kill_scd ();
381 void
382 crypto_free (struct crypto_s *crypto)
384 if (!crypto)
385 return;
387 crypto_free_non_keys (crypto);
388 strv_free (crypto->pubkey);
389 xfree (crypto->sigkey);
390 xfree (crypto->filename);
391 xfree (crypto);
394 gpgme_error_t
395 crypto_init_ctx (struct crypto_s *crypto, int no_pinentry,
396 char *passphrase_file)
398 gpgme_ctx_t ctx;
399 gpgme_keylist_mode_t keylist_mode;
400 gpgme_error_t rc;
402 rc = gpgme_new (&ctx);
403 if (rc)
404 return rc;
406 rc = gpgme_set_protocol (ctx, GPGME_PROTOCOL_OPENPGP);
407 if (!rc)
409 keylist_mode = gpgme_get_keylist_mode (ctx);
410 keylist_mode |= GPGME_KEYLIST_MODE_LOCAL|GPGME_KEYLIST_MODE_WITH_SECRET;
411 rc = gpgme_set_keylist_mode (ctx, keylist_mode);
412 if (!rc)
414 if (no_pinentry || passphrase_file)
415 rc = gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_LOOPBACK);
416 else
417 rc = gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_DEFAULT);
419 if (!rc)
421 gpgme_set_passphrase_cb (ctx, passphrase_cb, crypto);
422 gpgme_set_progress_cb (ctx, progress_cb, crypto);
423 gpgme_set_status_cb (ctx, status_cb, crypto);
424 crypto->ctx = ctx;
425 crypto->flags = 0;
427 if (passphrase_file)
429 crypto->keyfile = passphrase_file;
430 crypto->flags |= CRYPTO_FLAG_KEYFILE;
436 if (rc)
437 gpgme_release (ctx);
439 return rc;
442 void
443 crypto_set_keepalive ()
445 keepalive = config_get_integer ("global", "keepalive_interval");
448 gpg_error_t
449 crypto_init (struct crypto_s **crypto, void *ctx, const char *filename,
450 int no_pinentry, char *passphrase_file)
452 struct crypto_s *new = xcalloc (1, sizeof (struct crypto_s));
453 gpgme_error_t rc;
455 crypto_set_keepalive ();
457 if (!new)
458 return GPG_ERR_ENOMEM;
460 rc = crypto_init_ctx (new, no_pinentry, passphrase_file);
461 if (rc)
462 goto fail;
464 if (filename)
466 new->filename = str_dup (filename);
467 if (!new->filename)
469 rc = GPG_ERR_ENOMEM;
470 goto fail;
474 new->client_ctx = ctx;
475 *crypto = new;
476 return 0;
478 fail:
479 crypto_free (new);
480 return rc;
483 /* Converts a 40 byte key id to the 16 byte form. Needed for comparison of
484 * gpgme_recipient_t.keyid. */
485 gpg_error_t
486 crypto_keyid_to_16b_once (char *key)
488 size_t len = strlen (key);
490 if (len < 16)
491 return GPG_ERR_INV_ARG;
493 memmove (&key[0], &key[len-16], 16);
494 key[16] = 0;
495 return 0;
498 gpg_error_t
499 crypto_keyid_to_16b (char **keys)
501 char **p;
503 for (p = keys; p && *p; p++)
505 gpg_error_t rc = crypto_keyid_to_16b_once (*p);
506 if (rc)
507 return rc;
510 return 0;
513 gpgme_error_t
514 crypto_decrypt (struct client_s *client, struct crypto_s *crypto)
516 gpgme_data_t plain;
517 gpgme_error_t rc;
518 gpgme_data_t cipher;
519 int fd = -1;
520 struct stat st;
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 rc = open_check_file (crypto->filename, &fd, &st, 1);
532 if (!rc)
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 rc = send_status (client ? client->ctx : NULL, STATUS_DECRYPT, NULL);
540 if (!rc)
542 MUTEX_TRYLOCK (client->ctx, &crypto_mutex, rc,
543 client->lock_timeout);
544 if (!rc)
546 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
547 rc = gpgme_op_decrypt_verify_start (crypto->ctx, cipher, plain);
548 if (!rc)
550 STATUS_TIMEOUT_INIT(crypto);
553 if (!rc && crypto->progress_rc)
554 rc = crypto->progress_rc;
555 if (!rc)
556 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_DECRYPT, NULL);
557 TEST_CANCEL ();
558 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
560 pthread_cleanup_pop (1); // release_mutex_cb
563 pthread_cleanup_pop (1); // free_gpgme_data_cb (cipher)
566 pthread_cleanup_pop (1); // close (fd)
569 pthread_cleanup_pop (0); // free_gpgme_data_cb (plain)
571 if (rc)
573 free_gpgme_data_cb (plain);
574 return rc;
577 pthread_cleanup_push ((void *)free_gpgme_data_cb, plain);
578 result = gpgme_op_decrypt_result (crypto->ctx);
579 if (!result->unsupported_algorithm && !result->wrong_key_usage)
581 gpgme_recipient_t r;
583 for (r = result->recipients; r; r = r->next)
585 pthread_cleanup_push ((void *)strv_free, new_recipients);
586 log_write1 (_ ("%s: recipient: %s, status=%u"),
587 crypto->filename, r->keyid, r->status);
588 pthread_cleanup_pop (0);
589 pp = strv_cat(new_recipients, str_dup (r->keyid));
590 if (!pp)
592 rc = GPG_ERR_ENOMEM;
593 break;
596 new_recipients = pp;
599 else if (result->wrong_key_usage)
600 rc = GPG_ERR_WRONG_KEY_USAGE;
601 else if (result->unsupported_algorithm)
602 rc = GPG_ERR_UNSUPPORTED_ALGORITHM;
604 if (!rc)
606 gpgme_verify_result_t verify;
607 gpgme_signature_t s;
609 verify = gpgme_op_verify_result (crypto->ctx);
610 for (s = verify->signatures; s; s = s->next)
612 unsigned flags = s->summary;
614 pthread_cleanup_push ((void *)strv_free, new_signers);
615 log_write1 (_ ("%s: signer: %s, status=%u"),
616 crypto->filename, s->fpr, s->status);
617 pthread_cleanup_pop (0);
619 flags &= ~(GPGME_SIGSUM_KEY_EXPIRED|GPGME_SIGSUM_SIG_EXPIRED);
620 if (!flags)
621 flags |= GPGME_SIGSUM_VALID;
623 if (gpg_err_code (s->status) == GPG_ERR_KEY_EXPIRED)
624 s->status = 0;
626 if (s->status || s->wrong_key_usage || !(flags & GPGME_SIGSUM_VALID))
627 continue;
629 pp = strv_cat (new_signers, str_dup (s->fpr));
630 if (!pp)
632 rc = GPG_ERR_ENOMEM;
633 break;
636 new_signers = pp;
639 if (verify->signatures && !new_signers)
640 rc = GPG_ERR_BAD_SIGNATURE;
642 if (!rc)
644 xfree (crypto->plaintext);
645 crypto->plaintext = NULL;
646 crypto->plaintext_size = 0;
647 pthread_cleanup_push ((void *)strv_free, new_recipients);
648 pthread_cleanup_push ((void *)strv_free, new_signers);
649 rc = crypto_data_to_buf (plain, &crypto->plaintext,
650 &crypto->plaintext_size);
651 pthread_cleanup_pop (0);
652 pthread_cleanup_pop (0);
653 if (!rc)
655 strv_free (crypto->pubkey);
656 crypto->pubkey = new_recipients;
657 crypto_keyid_to_16b (crypto->pubkey);
659 xfree (crypto->sigkey);
660 crypto->sigkey = NULL;
661 if (new_signers)
663 crypto->sigkey = str_dup (*new_signers);
664 strv_free (new_signers);
665 crypto_keyid_to_16b_once (crypto->sigkey);
671 if (rc)
673 strv_free (new_recipients);
674 strv_free (new_signers);
677 pthread_cleanup_pop (1); // free_gpgme_data_cb (plain)
678 return rc;
681 void
682 crypto_free_key_list (gpgme_key_t *keys)
684 int i;
686 for (i = 0; keys && keys[i]; i++)
687 gpgme_key_unref (keys[i]);
689 xfree (keys);
692 /* Removes strings in 'prune' from 'a'. */
693 static char **
694 prune_keys (char **a, char **prune)
696 char **p;
698 for (p = prune; p && *p; p++)
700 char **ap;
702 for (ap = a; ap && *ap; ap++)
704 if (!strcmp (*ap, *p))
706 while (*ap)
708 *ap = *(ap+1);
709 ap++;
715 return a;
718 static void
719 remove_duplicates (char **a)
721 char **p;
723 for (p = a; p && *p; p++)
725 char **t;
727 for (t = p+1; t && *t; t++)
729 if (!strcmp (*p, *t))
731 char *tmp = *t;
733 while (*(t+1))
735 *t = *(t+1);
736 t++;
739 *t = NULL;
740 xfree (tmp);
741 remove_duplicates (a);
742 return;
748 gpgme_error_t
749 crypto_encrypt (struct client_s *client, struct crypto_s *crypto)
751 gpgme_error_t rc;
752 gpgme_data_t cipher = NULL;
753 gpgme_key_t *keys = NULL;
754 gpgme_key_t *sigkeys = NULL;
755 unsigned flags = 0;
756 int sign = 0;
758 if (!(crypto->flags & CRYPTO_FLAG_SYMMETRIC))
760 crypto_keyid_to_16b (crypto->save.pubkey);
761 remove_duplicates (crypto->save.pubkey);
762 rc = crypto_list_keys (crypto, crypto->save.pubkey, 0, &keys);
763 if (rc)
764 return rc;
767 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
768 rc = gpgme_data_new (&cipher);
769 pthread_cleanup_push ((void *)free_gpgme_data_cb, cipher);
770 if (!rc)
771 rc = gpgme_data_set_file_name (cipher, crypto->filename);
773 if (!rc && crypto->save.sigkey)
775 char **tmp = NULL;
777 crypto_keyid_to_16b_once (crypto->save.sigkey);
778 strv_printf (&tmp, "%s", crypto->save.sigkey);
779 pthread_cleanup_push ((void *)strv_free, tmp);
780 rc = crypto_list_keys (crypto, tmp, 1, &sigkeys);
781 pthread_cleanup_pop (1);
782 if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
783 rc = 0;
786 if (!rc)
788 gpgme_data_t plain = NULL;
790 pthread_cleanup_push ((void *)crypto_free_key_list, sigkeys);
791 rc = gpgme_data_new_from_mem (&plain, (char *)crypto->plaintext,
792 crypto->plaintext_size, 0);
793 pthread_cleanup_push ((void *)free_gpgme_data_cb, plain);
794 if (!rc)
796 int i;
798 gpgme_signers_clear (crypto->ctx);
800 for (i = 0; sigkeys && sigkeys[i]; i++)
801 gpgme_signers_add (crypto->ctx, sigkeys[i]);
804 if (!rc)
806 gpgme_data_set_encoding (cipher, GPGME_DATA_ENCODING_ARMOR);
807 rc = send_status (client ? client->ctx : NULL, STATUS_ENCRYPT, NULL);
810 if (!rc)
812 int f = config_get_boolean ("global", "encrypt_to");
814 if (!f)
815 flags |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
817 f = config_get_boolean ("global", "always_trust");
818 if (f)
819 flags |= GPGME_ENCRYPT_ALWAYS_TRUST;
821 if (!(crypto->flags & CRYPTO_FLAG_SYMMETRIC)
822 || (crypto->flags & CRYPTO_FLAG_SYMMETRIC && sigkeys))
823 sign = 1;
826 if (!rc)
827 MUTEX_TRYLOCK (client->ctx, &crypto_mutex, rc, client->lock_timeout);
829 if (!rc)
831 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
832 if (sign)
833 rc = gpgme_op_encrypt_sign_start (crypto->ctx, keys, flags, plain,
834 cipher);
835 else
836 rc = gpgme_op_encrypt_start (crypto->ctx, NULL, flags, plain,
837 cipher);
838 if (!rc)
840 STATUS_TIMEOUT_INIT (crypto);
843 if (!rc && crypto->progress_rc)
844 rc = crypto->progress_rc;
845 if (!rc)
846 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_ENCRYPT, NULL);
847 TEST_CANCEL();
848 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
850 pthread_cleanup_pop (1);
852 if (!rc)
854 gpgme_encrypt_result_t result;
855 gpgme_sign_result_t sresult;
856 gpgme_invalid_key_t inv;
857 gpgme_new_signature_t sigs;
858 char **prune = NULL;
859 char **p = NULL;
861 result = gpgme_op_encrypt_result (crypto->ctx);
862 inv = result->invalid_recipients;
863 while (inv)
865 pthread_cleanup_push ((void *)strv_free, prune);
866 log_write1 (_ ("%s: invalid recipient: %s, rc=%u"),
867 crypto->filename, inv->fpr, inv->reason);
868 pthread_cleanup_pop (0);
869 p = strv_cat (prune, str_dup(inv->fpr));
870 if (!p)
872 rc = GPG_ERR_ENOMEM;
873 strv_free (prune);
874 break;
877 prune = p;
878 inv = inv->next;
881 if (prune)
883 p = prune_keys (crypto->save.pubkey, prune);
884 crypto->save.pubkey = p;
885 strv_free (prune);
888 crypto_keyid_to_16b (crypto->save.pubkey);
889 sresult = gpgme_op_sign_result (crypto->ctx);
890 inv = sresult ? sresult->invalid_signers : NULL;
891 while (!rc && inv)
893 log_write1 (_ ("%s: invalid signer: %s, rc=%u"),
894 crypto->filename, inv->fpr, inv->reason);
895 inv = inv->next;
898 sigs = sresult ? sresult->signatures : NULL;
899 if (!rc && sigs)
901 p = NULL;
903 while (sigs)
905 char **pp;
907 pthread_cleanup_push ((void *)strv_free, p);
908 log_write1 (_ ("%s: signer: %s"), crypto->filename,
909 sigs->fpr);
910 pthread_cleanup_pop (0);
912 pp = strv_cat (p, str_dup (sigs->fpr));
913 if (!pp)
915 rc = GPG_ERR_ENOMEM;
916 strv_free (p);
917 break;
920 p = pp;
921 sigs = sigs->next;
924 if (!rc)
926 xfree (crypto->save.sigkey);
927 crypto->save.sigkey = str_dup (*p);
928 strv_free (p);
929 crypto_keyid_to_16b_once (crypto->save.sigkey);
930 crypto->cipher = cipher;
933 else if (!rc && crypto->flags & CRYPTO_FLAG_SYMMETRIC)
935 crypto->cipher = cipher;
937 else if (!rc)
939 if (!(crypto->flags & CRYPTO_FLAG_SYMMETRIC)
940 || (crypto->flags & CRYPTO_FLAG_SYMMETRIC && sigkeys))
941 rc = GPG_ERR_NO_SIGNATURE_SCHEME;
946 pthread_cleanup_pop (1); // free_gpgme_data_cb (plain)
947 pthread_cleanup_pop (1); // crypto_free_key_list (sigkeys)
950 pthread_cleanup_pop (0); // free_gpgme_data_cb (cipher)
951 pthread_cleanup_pop (1); // crypto_free_key_list (keys)
953 if (rc)
954 free_gpgme_data_cb (cipher);
956 return rc;
959 gpgme_error_t
960 crypto_passwd (struct client_s *client, struct crypto_s *crypto)
962 gpgme_error_t rc;
963 gpgme_key_t *keys = NULL;
965 /* Use SAVE instead for symmetric files. */
966 rc = crypto_is_symmetric (client->filename);
967 if (!rc || rc != GPG_ERR_BAD_DATA)
968 return !rc ? GPG_ERR_NOT_SUPPORTED : rc;
970 rc = crypto_list_keys (crypto, crypto->pubkey, 1, &keys);
971 if (rc)
972 return rc;
974 crypto->flags |= CRYPTO_FLAG_PASSWD;
975 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
976 rc = send_status (client->ctx, STATUS_KEEPALIVE, NULL);
977 if (!rc)
978 MUTEX_TRYLOCK (client->ctx, &crypto_mutex, rc, client->lock_timeout);
980 if (!rc)
982 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
983 rc = gpgme_op_passwd_start (crypto->ctx, keys[0], 0);
984 if (!rc)
986 STATUS_TIMEOUT_INIT (crypto);
989 if (!rc && crypto->progress_rc)
990 rc = crypto->progress_rc;
991 if (!rc)
992 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_KEEPALIVE, NULL);
993 TEST_CANCEL();
994 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
996 pthread_cleanup_pop (1);
999 pthread_cleanup_pop (1);
1000 return rc;
1003 /* Generate a new key pair. The resulting keyid's are stored in crypto->save.
1005 gpgme_error_t
1006 crypto_genkey (struct client_s *client, struct crypto_s *crypto)
1008 gpgme_error_t rc;
1010 rc = send_status (client ? client->ctx : NULL, STATUS_GENKEY, NULL);
1011 if (!rc)
1012 MUTEX_TRYLOCK ((client ? client->ctx : NULL), &crypto_mutex, rc,
1013 (client ? client->lock_timeout : 0));
1015 if (!rc)
1017 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
1018 if (crypto->save.mainkey)
1020 rc = gpgme_op_createsubkey_start (crypto->ctx,
1021 crypto->save.mainkey[0],
1022 crypto->save.algo,
1024 crypto->save.expire,
1025 crypto->save.flags);
1027 else
1029 rc = gpgme_op_createkey_start (crypto->ctx,
1030 crypto->save.userid,
1031 crypto->save.algo,
1033 crypto->save.expire,
1034 NULL,
1035 crypto->save.flags);
1038 if (!rc)
1040 STATUS_TIMEOUT_INIT (crypto);
1043 if (!rc && crypto->progress_rc)
1044 rc = crypto->progress_rc;
1045 if (!rc)
1046 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_GENKEY, NULL);
1047 TEST_CANCEL();
1048 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
1050 pthread_cleanup_pop (1);
1053 if (!rc)
1055 gpgme_key_t *keys = NULL;
1056 gpgme_genkey_result_t result;
1058 result = gpgme_op_genkey_result (crypto->ctx);
1059 xfree (crypto->save.sigkey);
1060 crypto->save.sigkey = str_dup (result->fpr);
1061 crypto_keyid_to_16b_once (crypto->save.sigkey);
1063 if (!rc)
1065 char **tmp = NULL;
1067 strv_printf (&tmp, "%s", crypto->save.sigkey);
1068 pthread_cleanup_push ((void *)strv_free, tmp);
1069 rc = crypto_list_keys (crypto, tmp, 1, &keys);
1070 pthread_cleanup_pop (1);
1073 if (!rc)
1075 gpgme_subkey_t key = keys[0]->subkeys;
1077 for (; key; key = key->next)
1079 if (key->can_encrypt)
1080 break;
1083 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
1084 rc = send_status (client ? client->ctx : NULL, STATUS_GENKEY, "%s %s",
1085 crypto->save.sigkey, key ? key->fpr : "");
1086 if (!rc && key)
1088 crypto->save.pubkey = strv_cat (crypto->save.pubkey,
1089 str_dup (key->fpr));
1090 crypto_keyid_to_16b (crypto->save.pubkey);
1093 pthread_cleanup_pop (1);
1097 return rc;
1100 #ifdef WITH_LIBACL
1101 static void
1102 acl_free_cb (void *arg)
1104 acl_t acl = arg ? (acl_t) arg : NULL;
1106 if (acl)
1107 acl_free (acl);
1109 #endif
1111 /* The advisory lock should be obtained before calling this function. */
1112 gpg_error_t
1113 crypto_write_file (struct crypto_s *crypto, unsigned char **r_crc,
1114 size_t *r_crclen)
1116 unsigned char *buf;
1117 size_t size, len;
1118 int fd;
1119 gpg_error_t rc;
1120 char tmp[PATH_MAX];
1121 struct stat st;
1122 mode_t mode = 0600;
1123 #ifdef WITH_LIBACL
1124 acl_t acl = NULL;
1125 #endif
1127 if (crypto->filename)
1129 if (lstat (crypto->filename, &st) == 0)
1131 mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
1133 if (!(mode & S_IWUSR))
1134 return GPG_ERR_EACCES;
1136 else if (errno != ENOENT)
1137 return gpg_error_from_errno (errno);
1139 snprintf (tmp, sizeof (tmp), "%s.XXXXXX", crypto->filename);
1140 mode_t tmode = umask (0600);
1141 fd = mkstemp (tmp);
1142 if (fd == -1)
1144 rc = gpg_error_from_errno (errno);
1145 umask (tmode);
1146 log_write ("%s: %s", tmp, pwmd_strerror (rc));
1147 return rc;
1150 umask (tmode);
1152 else
1153 fd = STDOUT_FILENO;
1155 rc = crypto_data_to_buf (crypto->cipher, &buf, &size);
1156 if (rc)
1158 if (crypto->filename)
1159 close (fd);
1160 return rc;
1163 pthread_cleanup_push ((void *)close_fd_cb, &fd);
1164 if (r_crc)
1165 rc = get_checksum_memory (buf, size, r_crc, r_crclen);
1167 if (!rc)
1169 pthread_cleanup_push ((void *)xfree, buf);
1170 len = write (fd, buf, size);
1171 pthread_cleanup_pop (1);
1172 if (len != size)
1173 rc = gpg_error_from_errno (errno);
1176 if (!rc)
1178 if (fsync (fd) != -1)
1180 if (crypto->filename && close (fd) != -1)
1182 #ifdef WITH_LIBACL
1183 acl = acl_get_file (crypto->filename, ACL_TYPE_ACCESS);
1184 if (!acl && errno == ENOENT)
1185 acl = acl_get_file (".", ACL_TYPE_DEFAULT);
1186 if (!acl)
1187 log_write ("ACL: %s: %s", crypto->filename,
1188 pwmd_strerror (gpg_error_from_errno (errno)));
1189 pthread_cleanup_push ((void *)acl_free_cb, acl);
1190 #endif
1192 fd = -1;
1193 if (config_get_boolean (crypto->filename, "backup"))
1195 char tmp2[PATH_MAX];
1197 snprintf (tmp2, sizeof (tmp2), "%s.backup", crypto->filename);
1198 if (rename (crypto->filename, tmp2) == -1)
1199 if (errno != ENOENT)
1200 rc = gpg_error_from_errno (errno);
1203 if (!rc && rename (tmp, crypto->filename) == -1)
1204 rc = gpg_error_from_errno (errno);
1206 if (!rc)
1208 if (chmod (crypto->filename, mode) == -1)
1209 log_write ("%s(%u): %s", __FILE__, __LINE__,
1210 pwmd_strerror (gpg_error_from_syserror ()));
1212 #ifdef WITH_LIBACL
1213 if (!rc && acl && acl_set_file (crypto->filename,
1214 ACL_TYPE_ACCESS, acl))
1215 log_write ("ACL: %s: %s", crypto->filename,
1216 pwmd_strerror (gpg_error_from_errno (errno)));
1217 pthread_cleanup_pop (1);
1218 #endif
1220 else if (crypto->filename)
1221 rc = gpg_error_from_errno (errno);
1223 if (!rc && fd != -1)
1225 char *datadir = str_asprintf ("%s/data", homedir);
1227 if (datadir)
1229 int dfd = open (datadir, O_RDONLY);
1231 if (dfd != -1)
1233 if (fsync (dfd) == -1)
1234 log_write ("%s %d: %s", __FILE__, __LINE__,
1235 pwmd_strerror (errno));
1237 close (dfd);
1239 else
1240 log_write ("%s %d: %s", __FILE__, __LINE__,
1241 pwmd_strerror (errno));
1243 xfree (datadir);
1247 else
1248 rc = gpg_error_from_errno (errno);
1251 pthread_cleanup_pop (0); // close (fd)
1252 if (fd != -1)
1253 close (fd);
1255 return rc;
1258 char *
1259 crypto_key_info (const gpgme_key_t key)
1261 struct string_s *string = string_new (NULL), *s;
1262 char *line = NULL;
1263 unsigned n, u;
1264 gpgme_subkey_t subkey;
1265 gpgme_user_id_t uid;
1267 if (!string)
1268 return NULL;
1270 for (u = 0, uid = key->uids; uid; uid = uid->next)
1271 u++;
1273 for (n = 0, subkey = key->subkeys; subkey; subkey = subkey->next)
1274 n++;
1276 s = string_append_printf (string, "%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%i:%s:%s:%s:%i:%u:%u",
1277 key->revoked, key->expired, key->disabled,
1278 key->invalid, key->can_encrypt, key->can_sign,
1279 key->can_certify, key->secret,
1280 key->can_authenticate, key->is_qualified,
1281 key->protocol,
1282 key->issuer_serial ? key->issuer_serial : "",
1283 key->issuer_name ? key->issuer_name : "",
1284 key->chain_id ? key->chain_id : "",
1285 key->owner_trust, u, n);
1286 if (!s)
1288 string_free (string, 1);
1289 return NULL;
1292 string = s;
1293 for (subkey = key->subkeys; subkey; subkey = subkey->next)
1295 char *tmp;
1297 s = string_append_printf (string, ":%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%i:%u",
1298 subkey->revoked, subkey->expired,
1299 subkey->disabled, subkey->invalid,
1300 subkey->can_encrypt, subkey->can_sign,
1301 subkey->can_certify, subkey->secret,
1302 subkey->can_authenticate, subkey->is_qualified,
1303 subkey->is_cardkey, subkey->pubkey_algo,
1304 subkey->length);
1305 if (!s)
1307 string_free (string, 1);
1308 return NULL;
1311 string = s;
1312 s = string_append_printf (string, ":%s:%s:%s:%li:%li:%s",
1313 subkey->keyid, subkey->fpr,
1314 subkey->keygrip ? subkey->keygrip : "",
1315 subkey->timestamp, subkey->expires,
1316 subkey->card_number ? subkey->card_number : "0");
1317 if (!s)
1319 string_free (string, 1);
1320 return NULL;
1323 string = s;
1324 tmp = gnupg_escape (subkey->curve);
1325 s = string_append_printf (string, ":%s", tmp ? tmp : "");
1326 xfree (tmp);
1327 if (!s)
1329 string_free (string, 1);
1330 return NULL;
1333 string = s;
1336 for (uid = key->uids; uid; uid = uid->next)
1338 char *userid, *name, *email, *comment;
1340 userid = gnupg_escape (uid->uid);
1341 name = gnupg_escape (uid->name);
1342 email = gnupg_escape (uid->email);
1343 comment = gnupg_escape (uid->comment);
1344 s = string_append_printf (string, ":%u:%u:%u:%s:%s:%s:%s",
1345 uid->revoked, uid->invalid, uid->validity,
1346 userid ? userid : "",
1347 name ? name : "",
1348 email ? email : "",
1349 comment ? comment : "");
1350 xfree (userid);
1351 xfree (name);
1352 xfree (email);
1353 xfree (comment);
1354 if (!s)
1356 string_free (string, 1);
1357 return NULL;
1360 string = s;
1363 line = string->str;
1364 string_free (string, 0);
1365 return line;
1368 gpg_error_t
1369 crypto_try_decrypt (struct client_s *client, int no_pinentry)
1371 struct crypto_s *crypto;
1372 gpg_error_t rc;
1373 char *keyfile = config_get_string (client->filename, "passphrase_file");
1375 rc = crypto_init (&crypto, client->ctx, client->filename, no_pinentry,
1376 keyfile);
1377 if (!rc)
1379 pthread_cleanup_push ((void *)crypto_free, crypto);
1380 rc = crypto_decrypt (client, crypto);
1381 pthread_cleanup_pop (1);
1383 else
1384 xfree (keyfile);
1386 return rc;
1389 /* The advisory lock should be obtained before calling this function. */
1390 gpg_error_t
1391 crypto_is_symmetric (const char *filename)
1393 int fd;
1394 uint8_t magic[2];
1395 ssize_t len;
1396 gpg_error_t rc;
1398 rc = open_check_file (filename, &fd, NULL, 1);
1399 if (rc)
1400 return rc;
1402 len = read (fd, &magic, sizeof(magic));
1403 close (fd);
1404 if (len != sizeof (magic))
1405 return GPG_ERR_INV_VALUE;
1407 // Always read as big endian.
1408 if (magic[0] != 0x8c || magic[1] != 0x0d)
1409 return GPG_ERR_BAD_DATA;
1411 return 0;
1414 gpg_error_t
1415 crypto_delete_key (struct client_s *client, struct crypto_s *crypto,
1416 const gpgme_key_t key, int secret)
1418 gpg_error_t rc;
1420 STATUS_TIMEOUT_INIT (crypto);
1421 rc = send_status (client->ctx, STATUS_DECRYPT, NULL);
1422 if (!rc)
1423 rc = gpgme_op_delete_start (crypto->ctx, key, 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;