SAVE: Fix crash with --sign-keyid.
[pwmd.git] / src / crypto.c
blob50bf1b572fd2f4a163b4ea3ba3376ea4795e0cdd
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>
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 int 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 #if 0
68 static gpgme_error_t
69 show_key_output (gpgme_key_t key)
71 gpgme_subkey_t keyp; // first is primary
73 for (keyp = key->subkeys; keyp; keyp = keyp->next)
75 fprintf(stderr, "keyid: %s, revoked: %i, expired: %i, disabled: %i, invalid: %i,"
76 "encrypt: %i, sign: %i, cert: %i, auth: %i, secret: %i\n",
77 keyp->keyid, keyp->revoked, keyp->expired, keyp->disabled,
78 keyp->invalid, keyp->can_encrypt, keyp->can_sign,
79 keyp->can_certify, keyp->can_authenticate, keyp->secret);
82 return 0;
84 #endif
86 static gpg_error_t
87 get_password (const char *keyfile, unsigned char **result, size_t *len)
89 struct stat st;
90 int fd;
91 unsigned char *buf = NULL;
92 gpg_error_t rc = 0;
94 log_write (_ ("obtaining passphrase from passphrase file"));
95 rc = open_check_file (keyfile, &fd, &st, 0);
96 if (rc)
97 return rc;
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 const char *keyword = "PASSPHRASE";
167 if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD_SIGN)
168 keyword = "SIGN_PASSPHRASE";
169 else if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD_NEW)
171 crypto->flags |= CRYPTO_FLAG_PASSWD_SIGN;
172 keyword = "NEW_PASSPHRASE";
174 else if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD)
175 crypto->flags |= CRYPTO_FLAG_PASSWD_NEW;
176 else if (!bad && crypto->flags & CRYPTO_FLAG_NEWFILE)
178 keyword = "NEW_PASSPHRASE";
179 if (crypto->save.sigkey)
180 crypto->flags |= CRYPTO_FLAG_PASSWD_SIGN;
183 rc = assuan_inquire (crypto->client_ctx, keyword, &result, &len, 0);
187 if (!rc)
189 pthread_cleanup_push ((void *)xfree, result);
191 if (!len)
192 gpgme_io_writen (fd, "\n", 1);
193 else
195 int nl = result[len-1] == '\n';
196 int ret;
198 ret = gpgme_io_writen (fd, result, len);
199 if (!ret && !nl)
200 gpgme_io_writen (fd, "\n", 1);
201 else if (ret)
202 rc = GPG_ERR_CANCELED;
205 pthread_cleanup_pop (1);
208 return rc;
211 static void
212 progress_cb (void *data, const char *what, int type, int current, int total)
214 struct crypto_s *crypto = data;
216 crypto->progress_rc = send_status (crypto->client_ctx, STATUS_GPGME,
217 "%s %i %i %i", what, type, current, total);
220 gpgme_error_t
221 crypto_data_to_buf (const gpgme_data_t data, unsigned char **result,
222 size_t *rlen)
224 off_t ret = gpgme_data_seek (data, 0, SEEK_SET);
225 gpgme_error_t rc;
226 size_t total = 0, size = BUFSIZE;
227 unsigned char *buf;
229 if (ret == -1)
230 return gpg_error_from_syserror ();
232 buf = xmalloc (size);
233 if (!buf)
234 return GPG_ERR_ENOMEM;
238 pthread_cleanup_push ((void *)xfree, buf);
239 ret = gpgme_data_read (data, &buf[total], BUFSIZE);
240 pthread_cleanup_pop (0);
241 if (ret > 0)
243 unsigned char *p;
245 total += ret;
246 size += BUFSIZE;
247 p = xrealloc (buf, size * sizeof(char));
248 if (!p)
250 xfree (buf);
251 return GPG_ERR_ENOMEM;
254 buf = p;
256 } while (ret > 0);
258 if (ret == -1)
260 rc = gpgme_err_code_from_syserror ();
261 xfree (buf);
262 return rc;
265 *result = buf;
266 *rlen = total;
267 return 0;
270 gpgme_error_t
271 crypto_list_keys (struct crypto_s *crypto, char *keys[], int secret,
272 gpgme_key_t **result)
274 gpgme_error_t rc;
275 gpgme_key_t key = NULL, *res = NULL;
276 size_t total = 0;
278 rc = gpgme_op_keylist_ext_start (crypto->ctx, (const char **)keys, secret, 0);
279 if (rc)
280 return rc;
282 STATUS_TIMEOUT_INIT (crypto);
285 gpgme_key_t *p;
287 pthread_cleanup_push ((void *)crypto_free_key_list, res);
288 rc = gpgme_op_keylist_next (crypto->ctx, &key);
289 pthread_cleanup_pop (0);
290 if (rc && gpgme_err_code(rc) != GPG_ERR_EOF)
291 break;
293 if (rc)
295 rc = 0;
296 break;
299 p = xrealloc (res, (total+2) * sizeof (gpgme_key_t));
300 if (!p)
302 rc = GPG_ERR_ENOMEM;
303 break;
306 res = p;
307 res[total++] = key;
308 res[total] = NULL;
309 pthread_cleanup_push ((void *)crypto_free_key_list, res);
310 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_KEEPALIVE, NULL);
311 pthread_cleanup_pop (0);
312 } while (!rc);
314 if (!rc)
316 rc = gpgme_op_keylist_end (crypto->ctx);
317 if (!rc)
319 *result = res;
320 rc = total ? 0 : secret ? GPG_ERR_NO_SECKEY : GPG_ERR_NO_PUBKEY;
323 else
324 crypto_free_key_list (res);
326 return rc;
329 void
330 crypto_free_save (struct save_s *save)
332 if (!save)
333 return;
335 strv_free (save->pubkey);
336 xfree (save->sigkey);
337 memset (save, 0, sizeof (struct save_s));
340 static gpg_error_t
341 crypto_kill_scd ()
343 return cache_kill_scd ();
346 static void
347 free_gpgme_data_cb (void *data)
349 gpgme_data_t d = data;
350 char *t;
351 size_t len;
353 if (!data)
354 return;
356 t = gpgme_data_release_and_get_mem (d, &len);
357 if (t)
358 wipememory (t, 0, len);
360 gpgme_free (t);
363 void
364 crypto_free_non_keys (struct crypto_s *crypto)
366 if (!crypto)
367 return;
369 if (crypto->ctx)
370 gpgme_release (crypto->ctx);
372 crypto->ctx = NULL;
373 xfree (crypto->plaintext);
374 crypto->plaintext = NULL;
375 crypto->plaintext_size = 0;
377 if (crypto->cipher)
378 free_gpgme_data_cb (crypto->cipher);
380 crypto->cipher = NULL;
381 crypto_free_save (&crypto->save);
382 xfree (crypto->keyfile);
383 crypto->keyfile = NULL;
384 crypto->flags &= ~CRYPTO_FLAG_KEYFILE;
385 (void)crypto_kill_scd ();
388 void
389 crypto_free (struct crypto_s *crypto)
391 if (!crypto)
392 return;
394 crypto_free_non_keys (crypto);
395 strv_free (crypto->pubkey);
396 xfree (crypto->sigkey);
397 xfree (crypto->filename);
398 xfree (crypto);
401 gpgme_error_t
402 crypto_init_ctx (struct crypto_s *crypto, int no_pinentry,
403 char *passphrase_file)
405 gpgme_ctx_t ctx;
406 gpgme_keylist_mode_t keylist_mode;
407 gpgme_error_t rc;
409 rc = gpgme_new (&ctx);
410 if (rc)
411 return rc;
413 rc = gpgme_set_protocol (ctx, GPGME_PROTOCOL_OPENPGP);
414 if (!rc)
416 keylist_mode = gpgme_get_keylist_mode (ctx);
417 keylist_mode |= GPGME_KEYLIST_MODE_LOCAL|GPGME_KEYLIST_MODE_WITH_SECRET;
418 rc = gpgme_set_keylist_mode (ctx, keylist_mode);
419 if (!rc)
421 if (no_pinentry || passphrase_file)
422 rc = gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_LOOPBACK);
423 else
424 rc = gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_DEFAULT);
426 if (!rc)
428 gpgme_set_passphrase_cb (ctx, passphrase_cb, crypto);
429 gpgme_set_progress_cb (ctx, progress_cb, crypto);
430 gpgme_set_status_cb (ctx, status_cb, crypto);
431 crypto->ctx = ctx;
432 crypto->flags = 0;
435 if (passphrase_file)
437 crypto->keyfile = passphrase_file;
438 crypto->flags |= CRYPTO_FLAG_KEYFILE;
443 if (rc)
444 gpgme_release (ctx);
446 return rc;
449 void
450 crypto_set_keepalive ()
452 keepalive = config_get_integer ("global", "keepalive_interval");
455 gpg_error_t
456 crypto_init (struct crypto_s **crypto, void *ctx, const char *filename,
457 int no_pinentry, char *passphrase_file)
459 struct crypto_s *new = xcalloc (1, sizeof (struct crypto_s));
460 gpgme_error_t rc;
462 crypto_set_keepalive ();
464 if (!new)
465 return GPG_ERR_ENOMEM;
467 rc = crypto_init_ctx (new, no_pinentry, passphrase_file);
468 if (rc)
469 goto fail;
471 if (filename)
473 new->filename = str_dup (filename);
474 if (!new->filename)
476 rc = GPG_ERR_ENOMEM;
477 goto fail;
481 new->client_ctx = ctx;
482 *crypto = new;
483 return 0;
485 fail:
486 crypto_free (new);
487 return rc;
490 /* Converts a 40 byte key id to the 16 byte form. Needed for comparison of
491 * gpgme_recipient_t.keyid. */
492 gpg_error_t
493 crypto_keyid_to_16b_once (char *key)
495 size_t len = strlen (key);
497 if (len < 16)
498 return GPG_ERR_INV_ARG;
500 memmove (&key[0], &key[len-16], 16);
501 key[16] = 0;
502 return 0;
505 gpg_error_t
506 crypto_keyid_to_16b (char **keys)
508 char **p;
510 for (p = keys; p && *p; p++)
512 gpg_error_t rc = crypto_keyid_to_16b_once (*p);
513 if (rc)
514 return rc;
517 return 0;
520 gpgme_error_t
521 crypto_decrypt (struct client_s *client, struct crypto_s *crypto)
523 gpgme_data_t plain;
524 gpgme_error_t rc;
525 gpgme_data_t cipher;
526 int fd;
527 struct stat st;
528 char **new_recipients = NULL;
529 char **new_signers = NULL;
530 char **pp;
531 gpgme_decrypt_result_t result;
533 rc = gpgme_data_new (&plain);
534 if (rc)
535 return rc;
537 pthread_cleanup_push ((void *)free_gpgme_data_cb, plain);
538 rc = open_check_file (crypto->filename, &fd, &st, 1);
539 if (!rc)
541 pthread_cleanup_push ((void *)close_fd_cb, &fd);
542 rc = gpgme_data_new_from_fd (&cipher, fd);
543 if (!rc)
545 pthread_cleanup_push ((void *)free_gpgme_data_cb, cipher);
546 rc = send_status (client ? client->ctx : NULL, STATUS_DECRYPT, NULL);
547 if (!rc)
549 MUTEX_TRYLOCK (client->ctx, &crypto_mutex, rc,
550 client->lock_timeout);
551 if (!rc)
553 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
554 rc = gpgme_op_decrypt_verify_start (crypto->ctx, cipher, plain);
555 if (!rc)
557 STATUS_TIMEOUT_INIT(crypto);
560 if (!rc && crypto->progress_rc)
561 rc = crypto->progress_rc;
562 if (!rc)
563 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_DECRYPT, NULL);
564 TEST_CANCEL ();
565 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
567 pthread_cleanup_pop (1); // release_mutex_cb
570 pthread_cleanup_pop (1); // free_gpgme_data_cb (cipher)
573 pthread_cleanup_pop (1); // close (fd)
576 pthread_cleanup_pop (0); // free_gpgme_data_cb (plain)
578 if (rc)
580 free_gpgme_data_cb (plain);
581 return rc;
584 pthread_cleanup_push ((void *)free_gpgme_data_cb, plain);
585 result = gpgme_op_decrypt_result (crypto->ctx);
586 if (!result->unsupported_algorithm && !result->wrong_key_usage)
588 gpgme_recipient_t r;
590 for (r = result->recipients; r; r = r->next)
592 pthread_cleanup_push ((void *)strv_free, new_recipients);
593 log_write1 (_ ("%s: recipient: %s, status=%u"),
594 crypto->filename, r->keyid, r->status);
595 pthread_cleanup_pop (0);
596 pp = strv_cat(new_recipients, str_dup (r->keyid));
597 if (!pp)
599 rc = GPG_ERR_ENOMEM;
600 break;
603 new_recipients = pp;
606 else if (result->wrong_key_usage)
607 rc = GPG_ERR_WRONG_KEY_USAGE;
608 else if (result->unsupported_algorithm)
609 rc = GPG_ERR_UNSUPPORTED_ALGORITHM;
611 if (!rc)
613 gpgme_verify_result_t verify;
614 gpgme_signature_t s;
616 verify = gpgme_op_verify_result (crypto->ctx);
618 for (s = verify->signatures; s; s = s->next)
620 pthread_cleanup_push ((void *)strv_free, new_signers);
621 log_write1 (_ ("%s: signer: %s, status=%u"),
622 crypto->filename, s->fpr, s->status);
623 pthread_cleanup_pop (0);
624 if (s->status || s->wrong_key_usage
625 || !(s->summary & GPGME_SIGSUM_VALID))
626 continue;
628 pp = strv_cat (new_signers, str_dup (s->fpr));
629 if (!pp)
631 rc = GPG_ERR_ENOMEM;
632 break;
635 new_signers = pp;
638 if (verify->signatures && !new_signers)
639 rc = GPG_ERR_BAD_SIGNATURE;
641 if (!rc)
643 xfree (crypto->plaintext);
644 crypto->plaintext = NULL;
645 crypto->plaintext_size = 0;
646 pthread_cleanup_push ((void *)strv_free, new_recipients);
647 pthread_cleanup_push ((void *)strv_free, new_signers);
648 rc = crypto_data_to_buf (plain, &crypto->plaintext,
649 &crypto->plaintext_size);
650 pthread_cleanup_pop (0);
651 pthread_cleanup_pop (0);
652 if (!rc)
654 strv_free (crypto->pubkey);
655 crypto->pubkey = new_recipients;
656 crypto_keyid_to_16b (crypto->pubkey);
658 xfree (crypto->sigkey);
659 crypto->sigkey = NULL;
660 if (new_signers)
662 crypto->sigkey = str_dup (*new_signers);
663 strv_free (new_signers);
664 crypto_keyid_to_16b_once (crypto->sigkey);
670 if (rc)
672 strv_free (new_recipients);
673 strv_free (new_signers);
676 pthread_cleanup_pop (1); // free_gpgme_data_cb (plain)
677 return rc;
680 void
681 crypto_free_key_list (gpgme_key_t *keys)
683 int i;
685 for (i = 0; keys && keys[i]; i++)
686 gpgme_key_unref (keys[i]);
688 xfree (keys);
691 /* Removes strings in 'prune' from 'a'. */
692 static char **
693 prune_keys (char **a, char **prune)
695 char **p;
697 for (p = prune; p && *p; p++)
699 char **ap;
701 for (ap = a; ap && *ap; ap++)
703 if (!strcmp (*ap, *p))
705 while (*ap)
707 *ap = *(ap+1);
708 ap++;
714 return a;
717 static void
718 remove_duplicates (char **a)
720 char **p;
722 for (p = a; p && *p; p++)
724 char **t;
726 for (t = p+1; t && *t; t++)
728 if (!strcmp (*p, *t))
730 char *tmp = *t;
732 while (*(t+1))
734 *t = *(t+1);
735 t++;
738 *t = NULL;
739 xfree (tmp);
740 remove_duplicates (a);
741 return;
747 gpgme_error_t
748 crypto_encrypt (struct client_s *client, struct crypto_s *crypto)
750 gpgme_error_t rc;
751 gpgme_data_t cipher = NULL;
752 gpgme_key_t *keys = NULL;
753 gpgme_key_t *sigkeys = NULL;
754 unsigned flags = 0;
755 int sign = 0;
757 if (!(crypto->flags & CRYPTO_FLAG_SYMMETRIC))
759 crypto_keyid_to_16b (crypto->save.pubkey);
760 remove_duplicates (crypto->save.pubkey);
761 rc = crypto_list_keys (crypto, crypto->save.pubkey, 0, &keys);
762 if (rc)
763 return rc;
766 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
767 rc = gpgme_data_new (&cipher);
768 pthread_cleanup_push ((void *)free_gpgme_data_cb, cipher);
769 if (!rc)
770 rc = gpgme_data_set_file_name (cipher, crypto->filename);
772 if (!rc && crypto->save.sigkey)
774 char **tmp = NULL;
776 crypto_keyid_to_16b_once (crypto->save.sigkey);
777 strv_printf (&tmp, "%s", crypto->save.sigkey);
778 pthread_cleanup_push ((void *)strv_free, tmp);
779 rc = crypto_list_keys (crypto, tmp, 1, &sigkeys);
780 pthread_cleanup_pop (1);
781 if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
782 rc = 0;
785 if (!rc)
787 gpgme_data_t plain = NULL;
789 pthread_cleanup_push ((void *)crypto_free_key_list, sigkeys);
790 rc = gpgme_data_new_from_mem (&plain, (char *)crypto->plaintext,
791 crypto->plaintext_size, 0);
792 pthread_cleanup_push ((void *)free_gpgme_data_cb, plain);
793 if (!rc)
795 int i;
797 gpgme_signers_clear (crypto->ctx);
799 for (i = 0; sigkeys && sigkeys[i]; i++)
800 gpgme_signers_add (crypto->ctx, sigkeys[i]);
803 if (!rc)
805 gpgme_data_set_encoding (cipher, GPGME_DATA_ENCODING_ARMOR);
806 rc = send_status (client ? client->ctx : NULL, STATUS_ENCRYPT, NULL);
809 if (!rc)
811 int f = config_get_boolean ("global", "encrypt_to");
813 if (!f)
814 flags |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
816 f = config_get_boolean ("global", "always_trust");
817 if (f)
818 flags |= GPGME_ENCRYPT_ALWAYS_TRUST;
820 if (!(crypto->flags & CRYPTO_FLAG_SYMMETRIC)
821 || (crypto->flags & CRYPTO_FLAG_SYMMETRIC && sigkeys))
822 sign = 1;
825 if (!rc)
826 MUTEX_TRYLOCK (client->ctx, &crypto_mutex, rc, client->lock_timeout);
828 if (!rc)
830 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
831 if (sign)
832 rc = gpgme_op_encrypt_sign_start (crypto->ctx, keys, flags, plain,
833 cipher);
834 else
835 rc = gpgme_op_encrypt_start (crypto->ctx, NULL, flags, plain,
836 cipher);
837 if (!rc)
839 STATUS_TIMEOUT_INIT (crypto);
842 if (!rc && crypto->progress_rc)
843 rc = crypto->progress_rc;
844 if (!rc)
845 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_ENCRYPT, NULL);
846 TEST_CANCEL();
847 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
849 pthread_cleanup_pop (1);
851 if (!rc)
853 gpgme_encrypt_result_t result;
854 gpgme_sign_result_t sresult;
855 gpgme_invalid_key_t inv;
856 gpgme_new_signature_t sigs;
857 char **prune = NULL;
858 char **p = NULL;
860 result = gpgme_op_encrypt_result (crypto->ctx);
861 inv = result->invalid_recipients;
862 while (inv)
864 pthread_cleanup_push ((void *)strv_free, prune);
865 log_write1 (_ ("%s: invalid recipient: %s, rc=%u"),
866 crypto->filename, inv->fpr, inv->reason);
867 pthread_cleanup_pop (0);
868 p = strv_cat (prune, str_dup(inv->fpr));
869 if (!p)
871 rc = GPG_ERR_ENOMEM;
872 strv_free (prune);
873 break;
876 prune = p;
877 inv = inv->next;
880 if (prune)
882 p = prune_keys (crypto->save.pubkey, prune);
883 crypto->save.pubkey = p;
884 strv_free (prune);
887 crypto_keyid_to_16b (crypto->save.pubkey);
888 sresult = gpgme_op_sign_result (crypto->ctx);
889 inv = sresult ? sresult->invalid_signers : NULL;
890 while (!rc && inv)
892 log_write1 (_ ("%s: invalid signer: %s, rc=%u"),
893 crypto->filename, inv->fpr, inv->reason);
894 inv = inv->next;
897 sigs = sresult ? sresult->signatures : NULL;
898 if (!rc && sigs)
900 p = NULL;
902 while (sigs)
904 char **pp;
906 pthread_cleanup_push ((void *)strv_free, p);
907 log_write1 (_ ("%s: signer: %s"), crypto->filename,
908 sigs->fpr);
909 pthread_cleanup_pop (0);
911 pp = strv_cat (p, str_dup (sigs->fpr));
912 if (!pp)
914 rc = GPG_ERR_ENOMEM;
915 strv_free (p);
916 break;
919 p = pp;
920 sigs = sigs->next;
923 if (!rc)
925 xfree (crypto->save.sigkey);
926 crypto->save.sigkey = str_dup (*p);
927 strv_free (p);
928 crypto_keyid_to_16b_once (crypto->save.sigkey);
929 crypto->cipher = cipher;
932 else if (!rc && crypto->flags & CRYPTO_FLAG_SYMMETRIC)
934 crypto->cipher = cipher;
936 else if (!rc)
938 if (!(crypto->flags & CRYPTO_FLAG_SYMMETRIC)
939 || (crypto->flags & CRYPTO_FLAG_SYMMETRIC && sigkeys))
940 rc = GPG_ERR_NO_SIGNATURE_SCHEME;
945 pthread_cleanup_pop (1); // free_gpgme_data_cb (plain)
946 pthread_cleanup_pop (1); // crypto_free_key_list (sigkeys)
949 pthread_cleanup_pop (0); // free_gpgme_data_cb (cipher)
950 pthread_cleanup_pop (1); // crypto_free_key_list (keys)
952 if (rc)
953 free_gpgme_data_cb (cipher);
955 return rc;
958 gpgme_error_t
959 crypto_passwd (struct client_s *client, struct crypto_s *crypto)
961 gpgme_error_t rc;
962 gpgme_key_t *keys = NULL;
964 /* Use SAVE instead for symmetric files. */
965 rc = crypto_is_symmetric (client->filename);
966 if (!rc || rc != GPG_ERR_BAD_DATA)
967 return !rc ? GPG_ERR_NOT_SUPPORTED : 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,
1006 const unsigned char *params)
1008 gpgme_error_t rc;
1010 if (strstr ((char *) params, "%pubring")
1011 || strstr ((char *) params, "%secring"))
1012 return GPG_ERR_INV_VALUE;
1014 rc = send_status (client ? client->ctx : NULL, STATUS_GENKEY, NULL);
1015 if (!rc)
1016 MUTEX_TRYLOCK (client->ctx, &crypto_mutex, rc, client->lock_timeout);
1018 if (!rc)
1020 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
1021 rc = gpgme_op_genkey_start (crypto->ctx, (const char *)params, NULL, NULL);
1022 if (!rc)
1024 STATUS_TIMEOUT_INIT (crypto);
1027 if (!rc && crypto->progress_rc)
1028 rc = crypto->progress_rc;
1029 if (!rc)
1030 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_GENKEY, NULL);
1031 TEST_CANCEL();
1032 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
1034 pthread_cleanup_pop (1);
1037 if (!rc)
1039 gpgme_key_t *keys = NULL;
1040 gpgme_genkey_result_t result;
1042 result = gpgme_op_genkey_result (crypto->ctx);
1043 xfree (crypto->save.sigkey);
1044 crypto->save.sigkey = str_dup (result->fpr);
1045 crypto_keyid_to_16b_once (crypto->save.sigkey);
1047 if (!rc)
1049 char **tmp = NULL;
1051 strv_printf (&tmp, "%s", crypto->save.sigkey);
1052 pthread_cleanup_push ((void *)strv_free, tmp);
1053 rc = crypto_list_keys (crypto, tmp, 1, &keys);
1054 pthread_cleanup_pop (1);
1057 if (!rc)
1059 gpgme_subkey_t key = keys[0]->subkeys;
1061 for (; key; key = key->next)
1063 if (key->can_encrypt)
1064 break;
1067 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
1068 rc = send_status (client ? client->ctx : NULL, STATUS_GENKEY, "%s %s",
1069 crypto->save.sigkey, key ? key->fpr : "");
1070 if (!rc)
1072 crypto->save.pubkey = strv_cat (crypto->save.pubkey,
1073 str_dup (key->fpr));
1074 crypto_keyid_to_16b (crypto->save.pubkey);
1077 pthread_cleanup_pop (1);
1081 return rc;
1084 char *
1085 crypto_default_key_params ()
1087 char *user = get_username (getuid());
1088 char *params = str_asprintf(
1089 "<GnupgKeyParms format=\"internal\">\n"
1090 " Key-Type: default\n"
1091 " Subkey-Type: default\n"
1092 " Name-Real: %s\n"
1093 " Name-Email: %s\n"
1094 " Expire-Date: 0\n"
1095 "</GnupgKeyParms>",
1096 getenv ("REALNAME") ? getenv ("REALNAME") : user,
1097 getenv ("EMAIL") ? getenv ("EMAIL") : user);
1099 xfree (user);
1100 return params;
1103 #ifdef WITH_LIBACL
1104 static void
1105 acl_free_cb (void *arg)
1107 acl_t acl = arg ? (acl_t) arg : NULL;
1109 if (acl)
1110 acl_free (acl);
1112 #endif
1114 /* The advisory lock should be obtained before calling this function. */
1115 gpg_error_t
1116 crypto_write_file (struct crypto_s *crypto)
1118 unsigned char *buf;
1119 size_t size, len;
1120 int fd;
1121 gpg_error_t rc;
1122 char tmp[PATH_MAX];
1123 struct stat st;
1124 mode_t mode = 0600;
1125 #ifdef WITH_LIBACL
1126 acl_t acl = NULL;
1127 #endif
1129 if (crypto->filename)
1131 if (lstat (crypto->filename, &st) == 0)
1133 mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
1135 if (!(mode & S_IWUSR))
1136 return GPG_ERR_EACCES;
1138 else if (errno != ENOENT)
1139 return gpg_error_from_errno (errno);
1141 snprintf (tmp, sizeof (tmp), "%s.XXXXXX", crypto->filename);
1142 mode_t tmode = umask (0600);
1143 fd = mkstemp (tmp);
1144 if (fd == -1)
1146 rc = gpg_error_from_errno (errno);
1147 umask (tmode);
1148 log_write ("%s: %s", tmp, pwmd_strerror (rc));
1149 return rc;
1152 umask (tmode);
1154 else
1155 fd = STDOUT_FILENO;
1157 rc = crypto_data_to_buf (crypto->cipher, &buf, &size);
1158 if (rc)
1160 if (crypto->filename)
1161 close (fd);
1162 return rc;
1165 pthread_cleanup_push ((void *)close_fd_cb, &fd);
1166 pthread_cleanup_push ((void *)xfree, buf);
1167 len = write (fd, buf, size);
1168 pthread_cleanup_pop (1);
1169 if (len != size)
1170 rc = gpg_error_from_errno (errno);
1172 if (!rc)
1174 if (fsync (fd) != -1)
1176 if (crypto->filename && close (fd) != -1)
1178 #ifdef WITH_LIBACL
1179 acl = acl_get_file (crypto->filename, ACL_TYPE_ACCESS);
1180 if (!acl && errno == ENOENT)
1181 acl = acl_get_file (".", ACL_TYPE_DEFAULT);
1182 if (!acl)
1183 log_write ("ACL: %s: %s", crypto->filename,
1184 pwmd_strerror (gpg_error_from_errno (errno)));
1185 pthread_cleanup_push ((void *)acl_free_cb, acl);
1186 #endif
1188 fd = -1;
1189 if (config_get_boolean (crypto->filename, "backup"))
1191 char tmp2[PATH_MAX];
1193 snprintf (tmp2, sizeof (tmp2), "%s.backup", crypto->filename);
1194 if (rename (crypto->filename, tmp2) == -1)
1195 if (errno != ENOENT)
1196 rc = gpg_error_from_errno (errno);
1199 if (!rc && rename (tmp, crypto->filename) == -1)
1200 rc = gpg_error_from_errno (errno);
1202 if (!rc)
1204 if (chmod (crypto->filename, mode) == -1)
1205 log_write ("%s(%u): %s", __FILE__, __LINE__,
1206 pwmd_strerror (gpg_error_from_syserror ()));
1208 #ifdef WITH_LIBACL
1209 if (!rc && acl && acl_set_file (crypto->filename,
1210 ACL_TYPE_ACCESS, acl))
1211 log_write ("ACL: %s: %s", crypto->filename,
1212 pwmd_strerror (gpg_error_from_errno (errno)));
1213 pthread_cleanup_pop (1);
1214 #endif
1216 else if (crypto->filename)
1217 rc = gpg_error_from_errno (errno);
1219 if (!rc && fd != -1)
1221 char *datadir = str_asprintf ("%s/data", homedir);
1223 if (datadir)
1225 int dfd = open (datadir, O_RDONLY);
1227 if (dfd != -1)
1229 if (fsync (dfd) == -1)
1230 log_write ("%s %d: %s", __FILE__, __LINE__,
1231 pwmd_strerror (errno));
1233 close (dfd);
1235 else
1236 log_write ("%s %d: %s", __FILE__, __LINE__,
1237 pwmd_strerror (errno));
1239 xfree (datadir);
1243 else
1244 rc = gpg_error_from_errno (errno);
1247 pthread_cleanup_pop (0); // close (fd)
1248 if (fd != -1)
1249 close (fd);
1250 return rc;
1253 char *
1254 crypto_key_info (const gpgme_key_t key)
1256 struct string_s *string = string_new (NULL), *s;
1257 char *line = NULL;
1258 unsigned n, u;
1259 gpgme_subkey_t subkey;
1260 gpgme_user_id_t uid;
1262 if (!string)
1263 return NULL;
1265 for (u = 0, uid = key->uids; uid; uid = uid->next)
1266 u++;
1268 for (n = 0, subkey = key->subkeys; subkey; subkey = subkey->next)
1269 n++;
1271 s = string_append_printf (string, "%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%i:%s:%s:%s:%i:%u:%u",
1272 key->revoked, key->expired, key->disabled,
1273 key->invalid, key->can_encrypt, key->can_sign,
1274 key->can_certify, key->secret,
1275 key->can_authenticate, key->is_qualified,
1276 key->protocol,
1277 key->issuer_serial ? key->issuer_serial : "",
1278 key->issuer_name ? key->issuer_name : "",
1279 key->chain_id ? key->chain_id : "",
1280 key->owner_trust, u, n);
1281 if (!s)
1283 string_free (string, 1);
1284 return NULL;
1287 string = s;
1288 for (subkey = key->subkeys; subkey; subkey = subkey->next)
1290 char *tmp;
1292 s = string_append_printf (string, ":%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%i:%u",
1293 subkey->revoked, subkey->expired,
1294 subkey->disabled, subkey->invalid,
1295 subkey->can_encrypt, subkey->can_sign,
1296 subkey->can_certify, subkey->secret,
1297 subkey->can_authenticate, subkey->is_qualified,
1298 subkey->is_cardkey, subkey->pubkey_algo,
1299 subkey->length);
1300 if (!s)
1302 string_free (string, 1);
1303 return NULL;
1306 string = s;
1307 s = string_append_printf (string, ":%s:%s:%s:%li:%li:%s",
1308 subkey->keyid, subkey->fpr,
1309 subkey->keygrip ? subkey->keygrip : "",
1310 subkey->timestamp, subkey->expires,
1311 subkey->card_number ? subkey->card_number : "0");
1312 if (!s)
1314 string_free (string, 1);
1315 return NULL;
1318 string = s;
1319 tmp = gnupg_escape (subkey->curve);
1320 s = string_append_printf (string, ":%s", tmp ? tmp : "");
1321 xfree (tmp);
1322 if (!s)
1324 string_free (string, 1);
1325 return NULL;
1328 string = s;
1331 for (uid = key->uids; uid; uid = uid->next)
1333 char *userid, *name, *email, *comment;
1335 userid = gnupg_escape (uid->uid);
1336 name = gnupg_escape (uid->name);
1337 email = gnupg_escape (uid->email);
1338 comment = gnupg_escape (uid->comment);
1339 s = string_append_printf (string, ":%u:%u:%u:%s:%s:%s:%s",
1340 uid->revoked, uid->invalid, uid->validity,
1341 userid ? userid : "",
1342 name ? name : "",
1343 email ? email : "",
1344 comment ? comment : "");
1345 xfree (userid);
1346 xfree (name);
1347 xfree (email);
1348 xfree (comment);
1349 if (!s)
1351 string_free (string, 1);
1352 return NULL;
1355 string = s;
1358 line = string->str;
1359 string_free (string, 0);
1360 return line;
1363 gpg_error_t
1364 crypto_try_decrypt (struct client_s *client, int no_pinentry)
1366 struct crypto_s *crypto;
1367 gpg_error_t rc;
1368 char *keyfile = config_get_string (client->filename, "passphrase_file");
1370 rc = crypto_init (&crypto, client->ctx, client->filename, no_pinentry,
1371 keyfile);
1372 if (!rc)
1374 pthread_cleanup_push ((void *)crypto_free, crypto);
1375 rc = crypto_decrypt (client, crypto);
1376 pthread_cleanup_pop (1);
1378 else
1379 xfree (keyfile);
1381 return rc;
1384 /* The advisory lock should be obtained before calling this function. */
1385 gpg_error_t
1386 crypto_is_symmetric (const char *filename)
1388 int fd;
1389 uint8_t magic[2];
1390 ssize_t len;
1391 gpg_error_t rc;
1393 rc = open_check_file (filename, &fd, NULL, 1);
1394 if (rc)
1395 return rc;
1397 len = read (fd, &magic, sizeof(magic));
1398 close (fd);
1399 if (len != sizeof (magic))
1400 return GPG_ERR_INV_VALUE;
1402 // Always read as big endian.
1403 if (magic[0] != 0x8c || magic[1] != 0x0d)
1404 return GPG_ERR_BAD_DATA;
1406 return 0;