ISCACHED: Return GPG_ERR_NO_DATA if deferred.
[pwmd.git] / src / crypto.c
blobb1b86309562aec8a7acdaf4d2620846c1dbefc60
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"
45 static int keepalive;
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 #if 0
65 static gpgme_error_t
66 show_key_output (gpgme_key_t key)
68 gpgme_subkey_t keyp; // first is primary
70 for (keyp = key->subkeys; keyp; keyp = keyp->next)
72 fprintf(stderr, "keyid: %s, revoked: %i, expired: %i, disabled: %i, invalid: %i,"
73 "encrypt: %i, sign: %i, cert: %i, auth: %i, secret: %i\n",
74 keyp->keyid, keyp->revoked, keyp->expired, keyp->disabled,
75 keyp->invalid, keyp->can_encrypt, keyp->can_sign,
76 keyp->can_certify, keyp->can_authenticate, keyp->secret);
79 return 0;
81 #endif
83 static gpg_error_t
84 get_password (const char *keyfile, unsigned char **result, size_t *len)
86 struct stat st;
87 int fd;
88 unsigned char *buf = NULL;
89 gpg_error_t rc = 0;
91 log_write (_ ("obtaining passphrase from passphrase file"));
92 if (stat (keyfile, &st) == -1)
93 return gpg_error_from_syserror ();
95 fd = open (keyfile, O_RDONLY);
96 if (fd == -1)
97 return gpg_error_from_syserror ();
99 buf = xmalloc (st.st_size+1);
100 if (buf)
102 size_t rlen = read (fd, buf, st.st_size);
104 if (rlen != st.st_size)
105 rc = GPG_ERR_ASS_READ_ERROR;
106 else
108 buf[rlen] = 0;
109 if (rlen && strlen ((char *)buf) != rlen)
110 rc = GPG_ERR_INV_PASSPHRASE;
112 if (!rc)
114 *result = buf;
115 *len = rlen;
119 else
120 rc = GPG_ERR_ENOMEM;
122 close (fd);
123 if (rc)
124 xfree (buf);
126 return rc;
129 static gpgme_error_t
130 status_cb (void *data, const char *keyword, const char *args)
132 struct crypto_s *crypto = data;
134 // Cache pushing.
135 if (!crypto->client_ctx)
136 return 0;
138 if (!strcmp (keyword, "INQUIRE_MAXLEN") &&
139 (crypto->flags & CRYPTO_FLAG_KEYFILE))
140 return 0;
142 return assuan_write_status (crypto->client_ctx, keyword, args);
145 static gpgme_error_t
146 passphrase_cb (void *data, const char *hint, const char *info, int bad, int fd)
148 struct crypto_s *crypto = data;
149 unsigned char *result = NULL;
150 size_t len;
151 gpg_error_t rc = 0;
153 if (crypto->flags & CRYPTO_FLAG_KEYFILE)
154 rc = get_password (crypto->keyfile, &result, &len);
155 else
157 if (hint)
158 rc = assuan_write_status (crypto->client_ctx, "PASSPHRASE_HINT", hint);
160 if (!rc && info)
161 rc = assuan_write_status (crypto->client_ctx, "PASSPHRASE_INFO", info);
163 if (!rc)
165 char *keyword = "PASSPHRASE";
167 /* FIXME: how to handle multiple signers */
168 if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD_SIGN)
169 keyword = "SIGN_PASSPHRASE";
170 else if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD_NEW)
172 crypto->flags |= CRYPTO_FLAG_PASSWD_SIGN;
173 keyword = "NEW_PASSPHRASE";
175 else if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD)
176 crypto->flags |= CRYPTO_FLAG_PASSWD_NEW;
177 else if (!bad && crypto->flags & CRYPTO_FLAG_NEWFILE)
179 keyword = "NEW_PASSPHRASE";
180 if (crypto->save.sigkey)
181 crypto->flags |= CRYPTO_FLAG_PASSWD_SIGN;
184 rc = assuan_inquire (crypto->client_ctx, keyword, &result, &len, 0);
188 if (!rc)
190 pthread_cleanup_push ((void *)xfree, result);
192 if (!len)
193 gpgme_io_writen (fd, "\n", 1);
194 else
196 int nl = result[len-1] == '\n';
197 int ret;
199 ret = gpgme_io_writen (fd, result, len);
200 if (!ret && !nl)
201 gpgme_io_writen (fd, "\n", 1);
202 else if (ret)
203 rc = GPG_ERR_CANCELED;
206 pthread_cleanup_pop (1);
209 return rc;
212 static void
213 progress_cb (void *data, const char *what, int type, int current, int total)
215 struct crypto_s *crypto = data;
217 crypto->progress_rc = send_status (crypto->client_ctx, STATUS_GPGME,
218 "%s %i %i %i", what, type, current, total);
221 gpgme_error_t
222 crypto_data_to_buf (const gpgme_data_t data, unsigned char **result,
223 size_t *rlen)
225 off_t ret = gpgme_data_seek (data, 0, SEEK_SET);
226 gpgme_error_t rc;
227 size_t total = 0, size = BUFSIZE;
228 unsigned char *buf;
230 if (ret == -1)
231 return gpg_error_from_syserror ();
233 buf = xmalloc (size);
234 if (!buf)
235 return GPG_ERR_ENOMEM;
239 pthread_cleanup_push ((void *)xfree, buf);
240 ret = gpgme_data_read (data, &buf[total], BUFSIZE);
241 pthread_cleanup_pop (0);
242 if (ret > 0)
244 unsigned char *p;
246 total += ret;
247 size += BUFSIZE;
248 p = xrealloc (buf, size * sizeof(char));
249 if (!p)
251 xfree (buf);
252 return GPG_ERR_ENOMEM;
255 buf = p;
257 } while (ret > 0);
259 if (ret == -1)
261 rc = gpgme_err_code_from_syserror ();
262 xfree (buf);
263 return rc;
266 *result = buf;
267 *rlen = total;
268 return 0;
271 static void
272 crypto_cancel_gpgme (void *data)
274 struct crypto_s *crypto = data;
275 struct client_s *client = assuan_get_pointer (crypto->client_ctx);
276 gpgme_error_t rc = 0;
278 if (client)
279 update_client_state (client, CLIENT_STATE_DISCON);
281 gpgme_cancel_async (crypto->ctx);
282 while (!gpgme_wait (crypto->ctx, &rc, 0) && !rc)
283 log_write1 (_ ("waiting for operation to finish"));
286 gpgme_error_t
287 crypto_list_keys (struct crypto_s *crypto, char *keys[], int secret,
288 gpgme_key_t **result)
290 gpgme_error_t rc;
291 gpgme_key_t key = NULL, *res = NULL;
292 size_t total = 0;
294 STATUS_TIMEOUT_INIT (crypto);
295 rc = gpgme_op_keylist_ext_start (crypto->ctx, (const char **)keys, secret, 0);
296 if (rc)
297 return rc;
299 pthread_cleanup_push ((void *)crypto_cancel_gpgme, crypto);
303 gpgme_key_t *p;
305 pthread_cleanup_push ((void *)crypto_free_key_list, res);
306 rc = gpgme_op_keylist_next (crypto->ctx, &key);
307 pthread_cleanup_pop (0);
308 if (rc && gpgme_err_code(rc) != GPG_ERR_EOF)
309 break;
311 if (rc)
313 rc = 0;
314 break;
317 p = xrealloc (res, (total+2) * sizeof (gpgme_key_t));
318 if (!p)
320 rc = GPG_ERR_ENOMEM;
321 break;
324 res = p;
325 res[total++] = key;
326 res[total] = NULL;
327 pthread_cleanup_push ((void *)crypto_free_key_list, res);
328 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_KEEPALIVE, NULL);
329 pthread_cleanup_pop (0);
330 } while (!rc);
332 pthread_cleanup_pop (0);
334 if (!rc)
336 rc = gpgme_op_keylist_end (crypto->ctx);
337 if (!rc)
339 *result = res;
340 rc = total ? 0 : secret ? GPG_ERR_NO_SECKEY : GPG_ERR_NO_PUBKEY;
343 else
344 crypto_free_key_list (res);
346 return rc;
349 void
350 crypto_free_save (struct save_s *save)
352 if (!save)
353 return;
355 strv_free (save->pubkey);
356 strv_free (save->sigkey);
357 memset (save, 0, sizeof (struct save_s));
360 static gpg_error_t
361 crypto_kill_scd ()
363 return cache_kill_scd ();
366 static void
367 free_gpgme_data_cb (void *data)
369 gpgme_data_t d = data;
370 char *t;
371 size_t len;
373 if (!data)
374 return;
376 t = gpgme_data_release_and_get_mem (d, &len);
377 if (t)
378 wipememory (t, 0, len);
380 gpgme_free (t);
383 void
384 crypto_free_non_keys (struct crypto_s *crypto)
386 if (!crypto)
387 return;
389 if (crypto->ctx)
390 gpgme_release (crypto->ctx);
392 crypto->ctx = NULL;
393 xfree (crypto->plaintext);
394 crypto->plaintext = NULL;
395 crypto->plaintext_size = 0;
397 if (crypto->cipher)
398 free_gpgme_data_cb (crypto->cipher);
400 crypto->cipher = NULL;
401 crypto_free_save (&crypto->save);
402 xfree (crypto->keyfile);
403 crypto->keyfile = NULL;
404 crypto->flags &= ~CRYPTO_FLAG_KEYFILE;
405 (void)crypto_kill_scd ();
408 void
409 crypto_free (struct crypto_s *crypto)
411 if (!crypto)
412 return;
414 crypto_free_non_keys (crypto);
415 strv_free (crypto->pubkey);
416 strv_free (crypto->sigkey);
417 xfree (crypto->filename);
418 xfree (crypto);
421 gpgme_error_t
422 crypto_init_ctx (struct crypto_s *crypto, int no_pinentry,
423 char *passphrase_file)
425 gpgme_ctx_t ctx;
426 gpgme_keylist_mode_t keylist_mode;
427 gpgme_error_t rc;
429 rc = gpgme_new (&ctx);
430 if (rc)
431 return rc;
433 rc = gpgme_set_protocol (ctx, GPGME_PROTOCOL_OPENPGP);
434 if (!rc)
436 keylist_mode = gpgme_get_keylist_mode (ctx);
437 keylist_mode |= GPGME_KEYLIST_MODE_LOCAL|GPGME_KEYLIST_MODE_WITH_SECRET;
438 rc = gpgme_set_keylist_mode (ctx, keylist_mode);
439 if (!rc)
441 if (no_pinentry || passphrase_file)
442 rc = gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_LOOPBACK);
443 else
444 rc = gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_DEFAULT);
446 if (!rc)
448 gpgme_set_passphrase_cb (ctx, passphrase_cb, crypto);
449 gpgme_set_progress_cb (ctx, progress_cb, crypto);
450 gpgme_set_status_cb (ctx, status_cb, crypto);
451 crypto->ctx = ctx;
452 crypto->flags = 0;
455 if (passphrase_file)
457 crypto->keyfile = passphrase_file;
458 crypto->flags |= CRYPTO_FLAG_KEYFILE;
463 if (rc)
464 gpgme_release (ctx);
466 return rc;
469 void
470 crypto_set_keepalive ()
472 keepalive = config_get_integer ("global", "keepalive_interval");
475 gpg_error_t
476 crypto_init (struct crypto_s **crypto, void *ctx, const char *filename,
477 int no_pinentry, char *passphrase_file)
479 struct crypto_s *new = xcalloc (1, sizeof (struct crypto_s));
480 gpgme_error_t rc;
482 crypto_set_keepalive ();
484 if (!new)
485 return GPG_ERR_ENOMEM;
487 rc = crypto_init_ctx (new, no_pinentry, passphrase_file);
488 if (rc)
489 goto fail;
491 if (filename)
493 new->filename = str_dup (filename);
494 if (!new->filename)
496 rc = GPG_ERR_ENOMEM;
497 goto fail;
501 new->client_ctx = ctx;
502 *crypto = new;
503 return 0;
505 fail:
506 crypto_free (new);
507 return rc;
510 /* Converts a 40 byte key id to the 16 byte form. Needed for comparison of
511 * gpgme_recipient_t.keyid. */
512 void
513 crypto_keyid_to_16b (char **keys)
515 char **p;
517 for (p = keys; p && *p; p++)
519 char *t = *p;
520 size_t len = strlen (t);
522 memmove (&t[0], &t[len-16], 16);
523 t[16] = 0;
527 gpgme_error_t
528 crypto_decrypt (struct client_s *client, struct crypto_s *crypto)
530 gpgme_data_t plain;
531 gpgme_error_t rc;
532 gpgme_data_t cipher;
533 int fd;
534 char **new_recipients = NULL;
535 char **new_signers = NULL;
536 char **pp;
537 gpgme_decrypt_result_t result;
539 rc = gpgme_data_new (&plain);
540 if (rc)
541 return rc;
543 pthread_cleanup_push ((void *)free_gpgme_data_cb, plain);
544 fd = open (crypto->filename, O_RDONLY);
545 if (fd != -1)
547 pthread_cleanup_push ((void *)cleanup_fd_cb, &fd);
548 rc = gpgme_data_new_from_fd (&cipher, fd);
549 if (!rc)
551 pthread_cleanup_push ((void *)free_gpgme_data_cb, cipher);
552 STATUS_TIMEOUT_INIT(crypto);
553 rc = send_status (client ? client->ctx : NULL, STATUS_DECRYPT, NULL);
554 if (!rc)
555 rc = gpgme_op_decrypt_verify_start (crypto->ctx, cipher, plain);
557 if (!rc)
559 pthread_cleanup_push ((void *)crypto_cancel_gpgme, crypto);
563 if (!rc && crypto->progress_rc)
564 rc = crypto->progress_rc;
566 if (!rc)
567 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_DECRYPT, NULL);
569 if (rc)
570 break;
571 } while (!gpgme_wait (crypto->ctx, &rc, 0) && !rc);
573 pthread_cleanup_pop (0); // cancellation
576 pthread_cleanup_pop (1); // free_gpgme_data_cb (cipher)
579 pthread_cleanup_pop (1); // close (fd)
581 else
582 rc = gpgme_err_code_from_syserror ();
584 pthread_cleanup_pop (0); // free_gpgme_data_cb (plain)
586 if (rc)
588 free_gpgme_data_cb (plain);
589 return rc;
592 pthread_cleanup_push ((void *)free_gpgme_data_cb, plain);
593 result = gpgme_op_decrypt_result (crypto->ctx);
594 if (!result->unsupported_algorithm && !result->wrong_key_usage)
596 gpgme_recipient_t r;
598 for (r = result->recipients; r; r = r->next)
600 pthread_cleanup_push ((void *)strv_free, new_recipients);
601 log_write1 (_ ("%s: recipient: %s, status=%u"),
602 crypto->filename, r->keyid, r->status);
603 pthread_cleanup_pop (0);
604 pp = strv_cat(new_recipients, str_dup (r->keyid));
605 if (!pp)
607 rc = GPG_ERR_ENOMEM;
608 break;
611 new_recipients = pp;
614 else if (result->wrong_key_usage)
615 rc = GPG_ERR_WRONG_KEY_USAGE;
616 else if (result->unsupported_algorithm)
617 rc = GPG_ERR_UNSUPPORTED_ALGORITHM;
619 if (!rc)
621 gpgme_verify_result_t result;
622 gpgme_signature_t s;
624 result = gpgme_op_verify_result (crypto->ctx);
626 for (s = result->signatures; s; s = s->next)
628 pthread_cleanup_push ((void *)strv_free, new_signers);
629 log_write1 (_ ("%s: signer: %s, status=%u"),
630 crypto->filename, s->fpr, s->status);
631 pthread_cleanup_pop (0);
632 if (s->status || s->wrong_key_usage
633 || !(s->summary & GPGME_SIGSUM_VALID))
634 continue;
636 pp = strv_cat (new_signers, str_dup (s->fpr));
637 if (!pp)
639 rc = GPG_ERR_ENOMEM;
640 break;
643 new_signers = pp;
646 if (result->signatures && !new_signers)
647 rc = GPG_ERR_BAD_SIGNATURE;
649 if (!rc)
651 xfree (crypto->plaintext);
652 crypto->plaintext = NULL;
653 crypto->plaintext_size = 0;
654 pthread_cleanup_push ((void *)strv_free, new_recipients);
655 pthread_cleanup_push ((void *)strv_free, new_signers);
656 rc = crypto_data_to_buf (plain, &crypto->plaintext,
657 &crypto->plaintext_size);
658 pthread_cleanup_pop (0);
659 pthread_cleanup_pop (0);
660 if (!rc)
662 strv_free (crypto->pubkey);
663 crypto->pubkey = new_recipients;
664 crypto_keyid_to_16b (crypto->pubkey);
665 strv_free (crypto->sigkey);
666 crypto->sigkey = new_signers;
667 crypto_keyid_to_16b (crypto->sigkey);
672 if (rc)
674 strv_free (new_recipients);
675 strv_free (new_signers);
678 pthread_cleanup_pop (1); // free_gpgme_data_cb (plain)
679 return rc;
682 void
683 crypto_free_key_list (gpgme_key_t *keys)
685 int i;
687 for (i = 0; keys && keys[i]; i++)
688 gpgme_key_unref (keys[i]);
690 xfree (keys);
693 /* Removes strings in 'prune' from 'a'. */
694 static char **
695 prune_keys (char **a, char **prune)
697 char **p;
699 for (p = prune; p && *p; p++)
701 char **ap;
703 for (ap = a; ap && *ap; ap++)
705 if (!strcmp (*ap, *p))
707 while (*ap)
709 *ap = *(ap+1);
710 ap++;
716 return a;
719 static void
720 remove_duplicates (char **a)
722 char **p;
724 for (p = a; p && *p; p++)
726 char **t;
728 for (t = p+1; t && *t; t++)
730 if (!strcmp (*p, *t))
732 char *tmp = *t;
734 while (*(t+1))
736 *t = *(t+1);
737 t++;
740 *t = NULL;
741 xfree (tmp);
742 remove_duplicates (a);
743 return;
749 gpgme_error_t
750 crypto_encrypt (struct client_s *client, struct crypto_s *crypto)
752 gpgme_error_t rc;
753 gpgme_data_t cipher = NULL;
754 gpgme_key_t *keys = NULL;
755 gpgme_key_t *sigkeys = NULL;
757 STATUS_TIMEOUT_INIT (crypto);
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
774 || !(crypto->flags & CRYPTO_FLAG_SYMMETRIC)))
776 crypto_keyid_to_16b (crypto->save.sigkey);
777 remove_duplicates (crypto->save.sigkey);
778 rc = crypto_list_keys (crypto, crypto->save.sigkey, 1, &sigkeys);
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]);
800 if (!i && !(crypto->flags & CRYPTO_FLAG_SYMMETRIC))
801 rc = GPG_ERR_NO_SIGNATURE_SCHEME;
804 if (!rc)
806 gpgme_data_set_encoding (cipher, GPGME_DATA_ENCODING_ARMOR);
808 rc = send_status (client ? client->ctx : NULL, STATUS_ENCRYPT, NULL);
809 if (!rc)
811 unsigned flags = 0;
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 rc = gpgme_op_encrypt_sign_start (crypto->ctx,
824 (crypto->flags & CRYPTO_FLAG_SYMMETRIC) ? NULL : keys,
825 flags, plain, cipher);
826 else
827 rc = gpgme_op_encrypt_start (crypto->ctx, NULL, flags,
828 plain, cipher);
832 if (!rc)
834 pthread_cleanup_push ((void *)crypto_cancel_gpgme, crypto);
838 if (!rc && crypto->progress_rc)
839 rc = crypto->progress_rc;
841 if (!rc)
842 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_ENCRYPT, NULL);
844 if (rc)
845 break;
846 } while (!gpgme_wait (crypto->ctx, &rc, 0) && !rc);
848 pthread_cleanup_pop (0);
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;
885 crypto_keyid_to_16b (crypto->save.pubkey);
886 sresult = gpgme_op_sign_result (crypto->ctx);
887 inv = sresult ? sresult->invalid_signers : NULL;
888 while (!rc && inv)
890 log_write1 (_ ("%s: invalid signer: %s, rc=%u"),
891 crypto->filename, inv->fpr, inv->reason);
892 inv = inv->next;
895 sigs = sresult ? sresult->signatures : NULL;
896 if (!rc && sigs)
898 p = NULL;
900 while (sigs)
902 char **pp;
904 pthread_cleanup_push ((void *)strv_free, p);
905 log_write1 (_ ("%s: signer: %s"), crypto->filename,
906 sigs->fpr);
907 pthread_cleanup_pop (0);
909 pp = strv_cat (p, str_dup (sigs->fpr));
910 if (!pp)
912 rc = GPG_ERR_ENOMEM;
913 strv_free (p);
914 break;
917 p = pp;
918 sigs = sigs->next;
921 if (!rc)
923 strv_free (crypto->save.sigkey);
924 crypto->save.sigkey = p;
925 crypto_keyid_to_16b (crypto->save.sigkey);
926 crypto->cipher = cipher;
929 else if (!rc && crypto->flags & CRYPTO_FLAG_SYMMETRIC)
931 crypto->cipher = cipher;
933 else if (!rc)
935 if (!(crypto->flags & CRYPTO_FLAG_SYMMETRIC)
936 || (crypto->flags & CRYPTO_FLAG_SYMMETRIC && sigkeys))
937 rc = GPG_ERR_NO_SIGNATURE_SCHEME;
942 pthread_cleanup_pop (1); // free_gpgme_data_cb (plain)
943 pthread_cleanup_pop (1); // crypto_free_key_list (sigkeys)
946 pthread_cleanup_pop (0); // free_gpgme_data_cb (cipher)
947 pthread_cleanup_pop (1); // crypto_free_key_list (keys)
949 if (rc)
950 free_gpgme_data_cb (cipher);
952 return rc;
955 gpgme_error_t
956 crypto_passwd (struct client_s *client, struct crypto_s *crypto)
958 gpgme_error_t rc;
959 gpgme_key_t *keys = NULL;
961 /* Use SAVE instead for symmetric files. */
962 rc = crypto_is_symmetric (client->filename);
963 if (!rc || rc != GPG_ERR_BAD_DATA)
964 return !rc ? GPG_ERR_NOT_SUPPORTED : rc;
966 rc = crypto_list_keys (crypto, crypto->pubkey, 1, &keys);
967 if (rc)
968 return rc;
970 crypto->flags |= CRYPTO_FLAG_PASSWD;
971 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
972 STATUS_TIMEOUT_INIT (crypto);
973 rc = send_status (client->ctx, STATUS_KEEPALIVE, NULL);
974 if (!rc)
975 rc = gpgme_op_passwd_start (crypto->ctx, keys[0], 0);
977 if (!rc)
979 pthread_cleanup_push ((void *)crypto_cancel_gpgme, crypto);
983 if (!rc && crypto->progress_rc)
984 rc = crypto->progress_rc;
986 if (!rc)
987 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_KEEPALIVE, NULL);
989 if (rc)
990 break;
991 } while (!gpgme_wait (crypto->ctx, &rc, 0) && !rc);
993 pthread_cleanup_pop (0);
996 pthread_cleanup_pop (1);
997 return rc;
1000 /* Generate a new key pair. The resulting keyid's are stored in crypto->save.
1002 gpgme_error_t
1003 crypto_genkey (struct client_s *client, struct crypto_s *crypto,
1004 const unsigned char *params)
1006 gpgme_genkey_result_t result;
1007 gpgme_error_t rc;
1009 if (strstr ((char *) params, "%pubring")
1010 || strstr ((char *) params, "%secring"))
1011 return GPG_ERR_INV_VALUE;
1013 STATUS_TIMEOUT_INIT (crypto);
1014 rc = send_status (client ? client->ctx : NULL, STATUS_GENKEY, NULL);
1015 if (!rc)
1016 rc = gpgme_op_genkey_start (crypto->ctx, (const char *)params, NULL, NULL);
1018 if (rc)
1019 return rc;
1021 pthread_cleanup_push ((void *)crypto_cancel_gpgme, crypto);
1025 if (!rc && crypto->progress_rc)
1026 rc = crypto->progress_rc;
1028 if (!rc)
1029 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_GENKEY, NULL);
1031 if (rc)
1032 break;
1033 } while (!gpgme_wait (crypto->ctx, &rc, 0) && !rc);
1035 pthread_cleanup_pop (0);
1037 if (!rc)
1039 gpgme_key_t *keys = NULL;
1041 result = gpgme_op_genkey_result (crypto->ctx);
1042 crypto->save.sigkey = strv_cat (crypto->save.sigkey,
1043 str_dup (result->fpr));
1044 crypto_keyid_to_16b (crypto->save.sigkey);
1046 rc = crypto_list_keys (crypto, crypto->save.sigkey, 1, &keys);
1047 if (!rc)
1049 gpgme_subkey_t key = keys[0]->subkeys;
1051 for (; key; key = key->next)
1053 if (key->can_encrypt)
1054 break;
1057 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
1058 rc = send_status (client ? client->ctx : NULL, STATUS_GENKEY, "%s %s",
1059 crypto->save.sigkey[0], key ? key->fpr : "");
1060 if (!rc)
1062 crypto->save.pubkey = strv_cat (crypto->save.pubkey,
1063 str_dup (key->fpr));
1064 crypto_keyid_to_16b (crypto->save.pubkey);
1067 pthread_cleanup_pop (1);
1071 return rc;
1074 char *
1075 crypto_default_key_params ()
1077 char *user = get_username (getuid());
1078 char *params = str_asprintf(
1079 "<GnupgKeyParms format=\"internal\">\n"
1080 " Key-Type: default\n"
1081 " Subkey-Type: default\n"
1082 " Name-Real: %s\n"
1083 " Name-Email: %s\n"
1084 " Expire-Date: 0\n"
1085 "</GnupgKeyParms>",
1086 getenv ("REALNAME") ? getenv ("REALNAME") : user,
1087 getenv ("EMAIL") ? getenv ("EMAIL") : user);
1089 xfree (user);
1090 return params;
1093 #ifdef WITH_LIBACL
1094 static void
1095 cleanup_acl (void *arg)
1097 acl_t acl = arg ? (acl_t) arg : NULL;
1099 if (acl)
1100 acl_free (acl);
1102 #endif
1104 /* The advisory lock should be obtained before calling this function. */
1105 gpg_error_t
1106 crypto_write_file (struct crypto_s *crypto)
1108 unsigned char *buf;
1109 size_t size, len;
1110 int fd;
1111 gpg_error_t rc;
1112 char tmp[PATH_MAX];
1113 struct stat st;
1114 mode_t mode = 0600;
1115 #ifdef WITH_LIBACL
1116 acl_t acl = NULL;
1117 #endif
1119 if (crypto->filename)
1121 if (lstat (crypto->filename, &st) == 0)
1123 mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
1125 if (!(mode & S_IWUSR))
1126 return GPG_ERR_EACCES;
1128 else if (errno != ENOENT)
1129 return gpg_error_from_errno (errno);
1131 snprintf (tmp, sizeof (tmp), "%s.XXXXXX", crypto->filename);
1132 mode_t tmode = umask (0600);
1133 fd = mkstemp (tmp);
1134 if (fd == -1)
1136 rc = gpg_error_from_errno (errno);
1137 umask (tmode);
1138 log_write ("%s: %s", tmp, pwmd_strerror (rc));
1139 return rc;
1142 umask (tmode);
1144 else
1145 fd = STDOUT_FILENO;
1147 rc = crypto_data_to_buf (crypto->cipher, &buf, &size);
1148 if (rc)
1150 if (crypto->filename)
1151 close (fd);
1152 return rc;
1155 pthread_cleanup_push ((void *)cleanup_fd_cb, &fd);
1156 pthread_cleanup_push ((void *)xfree, buf);
1157 len = write (fd, buf, size);
1158 pthread_cleanup_pop (1);
1159 if (len != size)
1160 rc = gpg_error_from_errno (errno);
1162 if (!rc)
1164 if (fsync (fd) != -1)
1166 if (crypto->filename && close (fd) != -1)
1168 #ifdef WITH_LIBACL
1169 acl = acl_get_file (crypto->filename, ACL_TYPE_ACCESS);
1170 if (!acl && errno == ENOENT)
1171 acl = acl_get_file (".", ACL_TYPE_DEFAULT);
1172 if (!acl)
1173 log_write ("ACL: %s: %s", crypto->filename,
1174 pwmd_strerror (gpg_error_from_errno (errno)));
1175 pthread_cleanup_push ((void *)cleanup_acl, acl);
1176 #endif
1178 fd = -1;
1179 if (config_get_boolean (crypto->filename, "backup"))
1181 char tmp2[PATH_MAX];
1183 snprintf (tmp2, sizeof (tmp2), "%s.backup", crypto->filename);
1184 if (rename (crypto->filename, tmp2) == -1)
1185 if (errno != ENOENT)
1186 rc = gpg_error_from_errno (errno);
1189 if (!rc && rename (tmp, crypto->filename) == -1)
1190 rc = gpg_error_from_errno (errno);
1192 if (!rc)
1193 chmod (crypto->filename, mode);
1194 #ifdef WITH_LIBACL
1195 if (!rc && acl && acl_set_file (crypto->filename,
1196 ACL_TYPE_ACCESS, acl))
1197 log_write ("ACL: %s: %s", crypto->filename,
1198 pwmd_strerror (gpg_error_from_errno (errno)));
1199 pthread_cleanup_pop (1);
1200 #endif
1202 else if (crypto->filename)
1203 rc = gpg_error_from_errno (errno);
1205 if (!rc && fd != -1)
1207 char *tmp = str_asprintf ("%s/data", homedir);
1209 if (tmp)
1211 int dfd = open (tmp, O_RDONLY);
1213 if (dfd != -1)
1215 if (fsync (dfd) == -1)
1216 log_write ("%s %d: %s", __FILE__, __LINE__,
1217 pwmd_strerror (errno));
1219 close (dfd);
1221 else
1222 log_write ("%s %d: %s", __FILE__, __LINE__,
1223 pwmd_strerror (errno));
1225 xfree (tmp);
1229 else
1230 rc = gpg_error_from_errno (errno);
1233 pthread_cleanup_pop (0); // close (fd)
1234 if (fd != -1)
1235 close (fd);
1236 return rc;
1239 char *
1240 crypto_key_info (const gpgme_key_t key)
1242 struct string_s *string = string_new (NULL), *s;
1243 char *line = NULL;
1244 unsigned n, u;
1245 gpgme_subkey_t subkey;
1246 gpgme_user_id_t uid;
1248 if (!string)
1249 return NULL;
1251 for (u = 0, uid = key->uids; uid; uid = uid->next)
1252 u++;
1254 for (n = 0, subkey = key->subkeys; subkey; subkey = subkey->next)
1255 n++;
1257 s = string_append_printf (string, "%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%i:%s:%s:%s:%i:%u:%u",
1258 key->revoked, key->expired, key->disabled,
1259 key->invalid, key->can_encrypt, key->can_sign,
1260 key->can_certify, key->secret,
1261 key->can_authenticate, key->is_qualified,
1262 key->protocol,
1263 key->issuer_serial ? key->issuer_serial : "",
1264 key->issuer_name ? key->issuer_name : "",
1265 key->chain_id ? key->chain_id : "",
1266 key->owner_trust, u, n);
1267 if (!s)
1269 string_free (string, 1);
1270 return NULL;
1273 string = s;
1274 for (subkey = key->subkeys; subkey; subkey = subkey->next)
1276 char *tmp;
1278 s = string_append_printf (string, ":%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%i:%u",
1279 subkey->revoked, subkey->expired,
1280 subkey->disabled, subkey->invalid,
1281 subkey->can_encrypt, subkey->can_sign,
1282 subkey->can_certify, subkey->secret,
1283 subkey->can_authenticate, subkey->is_qualified,
1284 subkey->is_cardkey, subkey->pubkey_algo,
1285 subkey->length);
1286 if (!s)
1288 string_free (string, 1);
1289 return NULL;
1292 string = s;
1293 s = string_append_printf (string, ":%s:%s:%s:%li:%li:%s",
1294 subkey->keyid, subkey->fpr,
1295 subkey->keygrip ? subkey->keygrip : "",
1296 subkey->timestamp, subkey->expires,
1297 subkey->card_number ? subkey->card_number : "0");
1298 if (!s)
1300 string_free (string, 1);
1301 return NULL;
1304 string = s;
1305 tmp = gnupg_escape (subkey->curve);
1306 s = string_append_printf (string, ":%s", tmp ? tmp : "");
1307 xfree (tmp);
1308 if (!s)
1310 string_free (string, 1);
1311 return NULL;
1314 string = s;
1317 for (uid = key->uids; uid; uid = uid->next)
1319 char *userid, *name, *email, *comment;
1321 userid = gnupg_escape (uid->uid);
1322 name = gnupg_escape (uid->name);
1323 email = gnupg_escape (uid->email);
1324 comment = gnupg_escape (uid->comment);
1325 s = string_append_printf (string, ":%u:%u:%u:%s:%s:%s:%s",
1326 uid->revoked, uid->invalid, uid->validity,
1327 userid ? userid : "",
1328 name ? name : "",
1329 email ? email : "",
1330 comment ? comment : "");
1331 xfree (userid);
1332 xfree (name);
1333 xfree (email);
1334 xfree (comment);
1335 if (!s)
1337 string_free (string, 1);
1338 return NULL;
1341 string = s;
1344 line = string->str;
1345 string_free (string, 0);
1346 return line;
1349 gpg_error_t
1350 crypto_try_decrypt (struct client_s *client, int no_pinentry)
1352 struct crypto_s *crypto;
1353 gpg_error_t rc;
1354 char *keyfile = config_get_string (client->filename, "passphrase_file");
1356 rc = crypto_init (&crypto, client->ctx, client->filename, no_pinentry,
1357 keyfile);
1358 if (!rc)
1360 pthread_cleanup_push ((void *)crypto_free, crypto);
1361 rc = crypto_decrypt (client, crypto);
1362 pthread_cleanup_pop (1);
1364 else
1365 xfree (keyfile);
1367 return rc;
1370 /* The advisory lock should be obtained before calling this function. */
1371 gpg_error_t
1372 crypto_is_symmetric (const char *filename)
1374 int fd;
1375 uint8_t magic[2];
1376 ssize_t len;
1378 fd = open (filename, O_RDONLY);
1379 if (fd == -1)
1380 return gpg_error_from_errno (errno);
1382 len = read (fd, &magic, sizeof(magic));
1383 close (fd);
1384 if (len != sizeof (magic))
1385 return GPG_ERR_INV_VALUE;
1387 // Always read as big endian.
1388 if (magic[0] != 0x8c || magic[1] != 0x0d)
1389 return GPG_ERR_BAD_DATA;
1391 return 0;