Fix some Coverity warnings and other fixes.
[libpwmd.git] / src / crypto.c
blob23bc281a84356186b0f3b7e1324651f8d0470cde
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 fd = open (keyfile, O_RDONLY);
96 if (fd == -1)
97 return gpg_error_from_syserror ();
99 if (fstat (fd, &st) == -1)
101 rc = gpg_error_from_syserror ();
102 close (fd);
103 return rc;
106 buf = xmalloc (st.st_size+1);
107 if (buf)
109 size_t rlen = read (fd, buf, st.st_size);
111 if (rlen != st.st_size)
112 rc = GPG_ERR_ASS_READ_ERROR;
113 else
115 buf[rlen] = 0;
116 if (rlen && strlen ((char *)buf) != rlen)
117 rc = GPG_ERR_INV_PASSPHRASE;
119 if (!rc)
121 *result = buf;
122 *len = rlen;
126 else
127 rc = GPG_ERR_ENOMEM;
129 close (fd);
130 if (rc)
131 xfree (buf);
133 return rc;
136 static gpgme_error_t
137 status_cb (void *data, const char *keyword, const char *args)
139 struct crypto_s *crypto = data;
141 // Cache pushing.
142 if (!crypto->client_ctx)
143 return 0;
145 if (!strcmp (keyword, "INQUIRE_MAXLEN") &&
146 (crypto->flags & CRYPTO_FLAG_KEYFILE))
147 return 0;
149 return assuan_write_status (crypto->client_ctx, keyword, args);
152 static gpgme_error_t
153 passphrase_cb (void *data, const char *hint, const char *info, int bad, int fd)
155 struct crypto_s *crypto = data;
156 unsigned char *result = NULL;
157 size_t len;
158 gpg_error_t rc = 0;
160 if (crypto->flags & CRYPTO_FLAG_KEYFILE)
161 rc = get_password (crypto->keyfile, &result, &len);
162 else
164 if (hint)
165 rc = assuan_write_status (crypto->client_ctx, "PASSPHRASE_HINT", hint);
167 if (!rc && info)
168 rc = assuan_write_status (crypto->client_ctx, "PASSPHRASE_INFO", info);
170 if (!rc)
172 const char *keyword = "PASSPHRASE";
174 /* FIXME: how to handle multiple signers */
175 if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD_SIGN)
176 keyword = "SIGN_PASSPHRASE";
177 else if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD_NEW)
179 crypto->flags |= CRYPTO_FLAG_PASSWD_SIGN;
180 keyword = "NEW_PASSPHRASE";
182 else if (!bad && crypto->flags & CRYPTO_FLAG_PASSWD)
183 crypto->flags |= CRYPTO_FLAG_PASSWD_NEW;
184 else if (!bad && crypto->flags & CRYPTO_FLAG_NEWFILE)
186 keyword = "NEW_PASSPHRASE";
187 if (crypto->save.sigkey)
188 crypto->flags |= CRYPTO_FLAG_PASSWD_SIGN;
191 rc = assuan_inquire (crypto->client_ctx, keyword, &result, &len, 0);
195 if (!rc)
197 pthread_cleanup_push ((void *)xfree, result);
199 if (!len)
200 gpgme_io_writen (fd, "\n", 1);
201 else
203 int nl = result[len-1] == '\n';
204 int ret;
206 ret = gpgme_io_writen (fd, result, len);
207 if (!ret && !nl)
208 gpgme_io_writen (fd, "\n", 1);
209 else if (ret)
210 rc = GPG_ERR_CANCELED;
213 pthread_cleanup_pop (1);
216 return rc;
219 static void
220 progress_cb (void *data, const char *what, int type, int current, int total)
222 struct crypto_s *crypto = data;
224 crypto->progress_rc = send_status (crypto->client_ctx, STATUS_GPGME,
225 "%s %i %i %i", what, type, current, total);
228 gpgme_error_t
229 crypto_data_to_buf (const gpgme_data_t data, unsigned char **result,
230 size_t *rlen)
232 off_t ret = gpgme_data_seek (data, 0, SEEK_SET);
233 gpgme_error_t rc;
234 size_t total = 0, size = BUFSIZE;
235 unsigned char *buf;
237 if (ret == -1)
238 return gpg_error_from_syserror ();
240 buf = xmalloc (size);
241 if (!buf)
242 return GPG_ERR_ENOMEM;
246 pthread_cleanup_push ((void *)xfree, buf);
247 ret = gpgme_data_read (data, &buf[total], BUFSIZE);
248 pthread_cleanup_pop (0);
249 if (ret > 0)
251 unsigned char *p;
253 total += ret;
254 size += BUFSIZE;
255 p = xrealloc (buf, size * sizeof(char));
256 if (!p)
258 xfree (buf);
259 return GPG_ERR_ENOMEM;
262 buf = p;
264 } while (ret > 0);
266 if (ret == -1)
268 rc = gpgme_err_code_from_syserror ();
269 xfree (buf);
270 return rc;
273 *result = buf;
274 *rlen = total;
275 return 0;
278 gpgme_error_t
279 crypto_list_keys (struct crypto_s *crypto, char *keys[], int secret,
280 gpgme_key_t **result)
282 gpgme_error_t rc;
283 gpgme_key_t key = NULL, *res = NULL;
284 size_t total = 0;
286 rc = gpgme_op_keylist_ext_start (crypto->ctx, (const char **)keys, secret, 0);
287 if (rc)
288 return rc;
290 STATUS_TIMEOUT_INIT (crypto);
293 gpgme_key_t *p;
295 pthread_cleanup_push ((void *)crypto_free_key_list, res);
296 rc = gpgme_op_keylist_next (crypto->ctx, &key);
297 pthread_cleanup_pop (0);
298 if (rc && gpgme_err_code(rc) != GPG_ERR_EOF)
299 break;
301 if (rc)
303 rc = 0;
304 break;
307 p = xrealloc (res, (total+2) * sizeof (gpgme_key_t));
308 if (!p)
310 rc = GPG_ERR_ENOMEM;
311 break;
314 res = p;
315 res[total++] = key;
316 res[total] = NULL;
317 pthread_cleanup_push ((void *)crypto_free_key_list, res);
318 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_KEEPALIVE, NULL);
319 pthread_cleanup_pop (0);
320 } while (!rc);
322 if (!rc)
324 rc = gpgme_op_keylist_end (crypto->ctx);
325 if (!rc)
327 *result = res;
328 rc = total ? 0 : secret ? GPG_ERR_NO_SECKEY : GPG_ERR_NO_PUBKEY;
331 else
332 crypto_free_key_list (res);
334 return rc;
337 void
338 crypto_free_save (struct save_s *save)
340 if (!save)
341 return;
343 strv_free (save->pubkey);
344 strv_free (save->sigkey);
345 memset (save, 0, sizeof (struct save_s));
348 static gpg_error_t
349 crypto_kill_scd ()
351 return cache_kill_scd ();
354 static void
355 free_gpgme_data_cb (void *data)
357 gpgme_data_t d = data;
358 char *t;
359 size_t len;
361 if (!data)
362 return;
364 t = gpgme_data_release_and_get_mem (d, &len);
365 if (t)
366 wipememory (t, 0, len);
368 gpgme_free (t);
371 void
372 crypto_free_non_keys (struct crypto_s *crypto)
374 if (!crypto)
375 return;
377 if (crypto->ctx)
378 gpgme_release (crypto->ctx);
380 crypto->ctx = NULL;
381 xfree (crypto->plaintext);
382 crypto->plaintext = NULL;
383 crypto->plaintext_size = 0;
385 if (crypto->cipher)
386 free_gpgme_data_cb (crypto->cipher);
388 crypto->cipher = NULL;
389 crypto_free_save (&crypto->save);
390 xfree (crypto->keyfile);
391 crypto->keyfile = NULL;
392 crypto->flags &= ~CRYPTO_FLAG_KEYFILE;
393 (void)crypto_kill_scd ();
396 void
397 crypto_free (struct crypto_s *crypto)
399 if (!crypto)
400 return;
402 crypto_free_non_keys (crypto);
403 strv_free (crypto->pubkey);
404 strv_free (crypto->sigkey);
405 xfree (crypto->filename);
406 xfree (crypto);
409 gpgme_error_t
410 crypto_init_ctx (struct crypto_s *crypto, int no_pinentry,
411 char *passphrase_file)
413 gpgme_ctx_t ctx;
414 gpgme_keylist_mode_t keylist_mode;
415 gpgme_error_t rc;
417 rc = gpgme_new (&ctx);
418 if (rc)
419 return rc;
421 rc = gpgme_set_protocol (ctx, GPGME_PROTOCOL_OPENPGP);
422 if (!rc)
424 keylist_mode = gpgme_get_keylist_mode (ctx);
425 keylist_mode |= GPGME_KEYLIST_MODE_LOCAL|GPGME_KEYLIST_MODE_WITH_SECRET;
426 rc = gpgme_set_keylist_mode (ctx, keylist_mode);
427 if (!rc)
429 if (no_pinentry || passphrase_file)
430 rc = gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_LOOPBACK);
431 else
432 rc = gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_DEFAULT);
434 if (!rc)
436 gpgme_set_passphrase_cb (ctx, passphrase_cb, crypto);
437 gpgme_set_progress_cb (ctx, progress_cb, crypto);
438 gpgme_set_status_cb (ctx, status_cb, crypto);
439 crypto->ctx = ctx;
440 crypto->flags = 0;
443 if (passphrase_file)
445 crypto->keyfile = passphrase_file;
446 crypto->flags |= CRYPTO_FLAG_KEYFILE;
451 if (rc)
452 gpgme_release (ctx);
454 return rc;
457 void
458 crypto_set_keepalive ()
460 keepalive = config_get_integer ("global", "keepalive_interval");
463 gpg_error_t
464 crypto_init (struct crypto_s **crypto, void *ctx, const char *filename,
465 int no_pinentry, char *passphrase_file)
467 struct crypto_s *new = xcalloc (1, sizeof (struct crypto_s));
468 gpgme_error_t rc;
470 crypto_set_keepalive ();
472 if (!new)
473 return GPG_ERR_ENOMEM;
475 rc = crypto_init_ctx (new, no_pinentry, passphrase_file);
476 if (rc)
477 goto fail;
479 if (filename)
481 new->filename = str_dup (filename);
482 if (!new->filename)
484 rc = GPG_ERR_ENOMEM;
485 goto fail;
489 new->client_ctx = ctx;
490 *crypto = new;
491 return 0;
493 fail:
494 crypto_free (new);
495 return rc;
498 /* Converts a 40 byte key id to the 16 byte form. Needed for comparison of
499 * gpgme_recipient_t.keyid. */
500 gpg_error_t
501 crypto_keyid_to_16b (char **keys)
503 char **p;
505 for (p = keys; p && *p; p++)
507 char *t = *p;
508 size_t len = strlen (t);
510 if (len < 16)
511 return GPG_ERR_INV_ARG;
513 memmove (&t[0], &t[len-16], 16);
514 t[16] = 0;
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 char **new_recipients = NULL;
528 char **new_signers = NULL;
529 char **pp;
530 gpgme_decrypt_result_t result;
532 rc = gpgme_data_new (&plain);
533 if (rc)
534 return rc;
536 pthread_cleanup_push ((void *)free_gpgme_data_cb, plain);
537 fd = open (crypto->filename, O_RDONLY);
538 if (fd != -1)
540 pthread_cleanup_push ((void *)close_fd_cb, &fd);
541 rc = gpgme_data_new_from_fd (&cipher, fd);
542 if (!rc)
544 pthread_cleanup_push ((void *)free_gpgme_data_cb, cipher);
545 rc = send_status (client ? client->ctx : NULL, STATUS_DECRYPT, NULL);
546 if (!rc)
548 MUTEX_TRYLOCK (client->ctx, &crypto_mutex, rc,
549 client->lock_timeout);
550 if (!rc)
552 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
553 rc = gpgme_op_decrypt_verify_start (crypto->ctx, cipher, plain);
554 if (!rc)
556 STATUS_TIMEOUT_INIT(crypto);
559 if (!rc && crypto->progress_rc)
560 rc = crypto->progress_rc;
561 if (!rc)
562 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_DECRYPT, NULL);
563 TEST_CANCEL ();
564 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
566 pthread_cleanup_pop (1); // release_mutex_cb
569 pthread_cleanup_pop (1); // free_gpgme_data_cb (cipher)
572 pthread_cleanup_pop (1); // close (fd)
574 else
575 rc = gpgme_err_code_from_syserror ();
577 pthread_cleanup_pop (0); // free_gpgme_data_cb (plain)
579 if (rc)
581 free_gpgme_data_cb (plain);
582 return rc;
585 pthread_cleanup_push ((void *)free_gpgme_data_cb, plain);
586 result = gpgme_op_decrypt_result (crypto->ctx);
587 if (!result->unsupported_algorithm && !result->wrong_key_usage)
589 gpgme_recipient_t r;
591 for (r = result->recipients; r; r = r->next)
593 pthread_cleanup_push ((void *)strv_free, new_recipients);
594 log_write1 (_ ("%s: recipient: %s, status=%u"),
595 crypto->filename, r->keyid, r->status);
596 pthread_cleanup_pop (0);
597 pp = strv_cat(new_recipients, str_dup (r->keyid));
598 if (!pp)
600 rc = GPG_ERR_ENOMEM;
601 break;
604 new_recipients = pp;
607 else if (result->wrong_key_usage)
608 rc = GPG_ERR_WRONG_KEY_USAGE;
609 else if (result->unsupported_algorithm)
610 rc = GPG_ERR_UNSUPPORTED_ALGORITHM;
612 if (!rc)
614 gpgme_verify_result_t verify;
615 gpgme_signature_t s;
617 verify = gpgme_op_verify_result (crypto->ctx);
619 for (s = verify->signatures; s; s = s->next)
621 pthread_cleanup_push ((void *)strv_free, new_signers);
622 log_write1 (_ ("%s: signer: %s, status=%u"),
623 crypto->filename, s->fpr, s->status);
624 pthread_cleanup_pop (0);
625 if (s->status || s->wrong_key_usage
626 || !(s->summary & 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);
658 strv_free (crypto->sigkey);
659 crypto->sigkey = new_signers;
660 crypto_keyid_to_16b (crypto->sigkey);
665 if (rc)
667 strv_free (new_recipients);
668 strv_free (new_signers);
671 pthread_cleanup_pop (1); // free_gpgme_data_cb (plain)
672 return rc;
675 void
676 crypto_free_key_list (gpgme_key_t *keys)
678 int i;
680 for (i = 0; keys && keys[i]; i++)
681 gpgme_key_unref (keys[i]);
683 xfree (keys);
686 /* Removes strings in 'prune' from 'a'. */
687 static char **
688 prune_keys (char **a, char **prune)
690 char **p;
692 for (p = prune; p && *p; p++)
694 char **ap;
696 for (ap = a; ap && *ap; ap++)
698 if (!strcmp (*ap, *p))
700 while (*ap)
702 *ap = *(ap+1);
703 ap++;
709 return a;
712 static void
713 remove_duplicates (char **a)
715 char **p;
717 for (p = a; p && *p; p++)
719 char **t;
721 for (t = p+1; t && *t; t++)
723 if (!strcmp (*p, *t))
725 char *tmp = *t;
727 while (*(t+1))
729 *t = *(t+1);
730 t++;
733 *t = NULL;
734 xfree (tmp);
735 remove_duplicates (a);
736 return;
742 gpgme_error_t
743 crypto_encrypt (struct client_s *client, struct crypto_s *crypto)
745 gpgme_error_t rc;
746 gpgme_data_t cipher = NULL;
747 gpgme_key_t *keys = NULL;
748 gpgme_key_t *sigkeys = NULL;
749 unsigned flags = 0;
750 int sign = 0;
752 if (!(crypto->flags & CRYPTO_FLAG_SYMMETRIC))
754 crypto_keyid_to_16b (crypto->save.pubkey);
755 remove_duplicates (crypto->save.pubkey);
756 rc = crypto_list_keys (crypto, crypto->save.pubkey, 0, &keys);
757 if (rc)
758 return rc;
761 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
762 rc = gpgme_data_new (&cipher);
763 pthread_cleanup_push ((void *)free_gpgme_data_cb, cipher);
764 if (!rc)
765 rc = gpgme_data_set_file_name (cipher, crypto->filename);
767 if (!rc && (crypto->save.sigkey
768 || !(crypto->flags & CRYPTO_FLAG_SYMMETRIC)))
770 crypto_keyid_to_16b (crypto->save.sigkey);
771 remove_duplicates (crypto->save.sigkey);
772 rc = crypto_list_keys (crypto, crypto->save.sigkey, 1, &sigkeys);
773 if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
774 rc = 0;
777 if (!rc)
779 gpgme_data_t plain = NULL;
781 pthread_cleanup_push ((void *)crypto_free_key_list, sigkeys);
782 rc = gpgme_data_new_from_mem (&plain, (char *)crypto->plaintext,
783 crypto->plaintext_size, 0);
784 pthread_cleanup_push ((void *)free_gpgme_data_cb, plain);
785 if (!rc)
787 int i;
789 gpgme_signers_clear (crypto->ctx);
791 for (i = 0; sigkeys && sigkeys[i]; i++)
792 gpgme_signers_add (crypto->ctx, sigkeys[i]);
794 if (!i && !(crypto->flags & CRYPTO_FLAG_SYMMETRIC))
795 rc = GPG_ERR_NO_SIGNATURE_SCHEME;
798 if (!rc)
800 gpgme_data_set_encoding (cipher, GPGME_DATA_ENCODING_ARMOR);
801 rc = send_status (client ? client->ctx : NULL, STATUS_ENCRYPT, NULL);
804 if (!rc)
806 int f = config_get_boolean ("global", "encrypt_to");
808 if (!f)
809 flags |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
811 f = config_get_boolean ("global", "always_trust");
812 if (f)
813 flags |= GPGME_ENCRYPT_ALWAYS_TRUST;
815 if (!(crypto->flags & CRYPTO_FLAG_SYMMETRIC)
816 || (crypto->flags & CRYPTO_FLAG_SYMMETRIC && sigkeys))
817 sign = 1;
820 if (!rc)
821 MUTEX_TRYLOCK (client->ctx, &crypto_mutex, rc, client->lock_timeout);
823 if (!rc)
825 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
826 if (sign)
827 rc = gpgme_op_encrypt_sign_start (crypto->ctx, keys, flags, plain,
828 cipher);
829 else
830 rc = gpgme_op_encrypt_start (crypto->ctx, NULL, flags, plain,
831 cipher);
832 if (!rc)
834 STATUS_TIMEOUT_INIT (crypto);
837 if (!rc && crypto->progress_rc)
838 rc = crypto->progress_rc;
839 if (!rc)
840 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_ENCRYPT, NULL);
841 TEST_CANCEL();
842 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
844 pthread_cleanup_pop (1);
846 if (!rc)
848 gpgme_encrypt_result_t result;
849 gpgme_sign_result_t sresult;
850 gpgme_invalid_key_t inv;
851 gpgme_new_signature_t sigs;
852 char **prune = NULL;
853 char **p = NULL;
855 result = gpgme_op_encrypt_result (crypto->ctx);
856 inv = result->invalid_recipients;
857 while (inv)
859 pthread_cleanup_push ((void *)strv_free, prune);
860 log_write1 (_ ("%s: invalid recipient: %s, rc=%u"),
861 crypto->filename, inv->fpr, inv->reason);
862 pthread_cleanup_pop (0);
863 p = strv_cat (prune, str_dup(inv->fpr));
864 if (!p)
866 rc = GPG_ERR_ENOMEM;
867 strv_free (prune);
868 break;
871 prune = p;
872 inv = inv->next;
875 if (prune)
877 p = prune_keys (crypto->save.pubkey, prune);
878 crypto->save.pubkey = p;
879 strv_free (prune);
882 crypto_keyid_to_16b (crypto->save.pubkey);
883 sresult = gpgme_op_sign_result (crypto->ctx);
884 inv = sresult ? sresult->invalid_signers : NULL;
885 while (!rc && inv)
887 log_write1 (_ ("%s: invalid signer: %s, rc=%u"),
888 crypto->filename, inv->fpr, inv->reason);
889 inv = inv->next;
892 sigs = sresult ? sresult->signatures : NULL;
893 if (!rc && sigs)
895 p = NULL;
897 while (sigs)
899 char **pp;
901 pthread_cleanup_push ((void *)strv_free, p);
902 log_write1 (_ ("%s: signer: %s"), crypto->filename,
903 sigs->fpr);
904 pthread_cleanup_pop (0);
906 pp = strv_cat (p, str_dup (sigs->fpr));
907 if (!pp)
909 rc = GPG_ERR_ENOMEM;
910 strv_free (p);
911 break;
914 p = pp;
915 sigs = sigs->next;
918 if (!rc)
920 strv_free (crypto->save.sigkey);
921 crypto->save.sigkey = p;
922 crypto_keyid_to_16b (crypto->save.sigkey);
923 crypto->cipher = cipher;
926 else if (!rc && crypto->flags & CRYPTO_FLAG_SYMMETRIC)
928 crypto->cipher = cipher;
930 else if (!rc)
932 if (!(crypto->flags & CRYPTO_FLAG_SYMMETRIC)
933 || (crypto->flags & CRYPTO_FLAG_SYMMETRIC && sigkeys))
934 rc = GPG_ERR_NO_SIGNATURE_SCHEME;
939 pthread_cleanup_pop (1); // free_gpgme_data_cb (plain)
940 pthread_cleanup_pop (1); // crypto_free_key_list (sigkeys)
943 pthread_cleanup_pop (0); // free_gpgme_data_cb (cipher)
944 pthread_cleanup_pop (1); // crypto_free_key_list (keys)
946 if (rc)
947 free_gpgme_data_cb (cipher);
949 return rc;
952 gpgme_error_t
953 crypto_passwd (struct client_s *client, struct crypto_s *crypto)
955 gpgme_error_t rc;
956 gpgme_key_t *keys = NULL;
958 /* Use SAVE instead for symmetric files. */
959 rc = crypto_is_symmetric (client->filename);
960 if (!rc || rc != GPG_ERR_BAD_DATA)
961 return !rc ? GPG_ERR_NOT_SUPPORTED : rc;
963 rc = crypto_list_keys (crypto, crypto->pubkey, 1, &keys);
964 if (rc)
965 return rc;
967 crypto->flags |= CRYPTO_FLAG_PASSWD;
968 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
969 rc = send_status (client->ctx, STATUS_KEEPALIVE, NULL);
970 if (!rc)
971 MUTEX_TRYLOCK (client->ctx, &crypto_mutex, rc, client->lock_timeout);
973 if (!rc)
975 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
976 rc = gpgme_op_passwd_start (crypto->ctx, keys[0], 0);
977 if (!rc)
979 STATUS_TIMEOUT_INIT (crypto);
982 if (!rc && crypto->progress_rc)
983 rc = crypto->progress_rc;
984 if (!rc)
985 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_KEEPALIVE, NULL);
986 TEST_CANCEL();
987 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
989 pthread_cleanup_pop (1);
992 pthread_cleanup_pop (1);
993 return rc;
996 /* Generate a new key pair. The resulting keyid's are stored in crypto->save.
998 gpgme_error_t
999 crypto_genkey (struct client_s *client, struct crypto_s *crypto,
1000 const unsigned char *params)
1002 gpgme_error_t rc;
1004 if (strstr ((char *) params, "%pubring")
1005 || strstr ((char *) params, "%secring"))
1006 return GPG_ERR_INV_VALUE;
1008 rc = send_status (client ? client->ctx : NULL, STATUS_GENKEY, NULL);
1009 if (!rc)
1010 MUTEX_TRYLOCK (client->ctx, &crypto_mutex, rc, client->lock_timeout);
1012 if (!rc)
1014 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
1015 rc = gpgme_op_genkey_start (crypto->ctx, (const char *)params, NULL, NULL);
1016 if (!rc)
1018 STATUS_TIMEOUT_INIT (crypto);
1021 if (!rc && crypto->progress_rc)
1022 rc = crypto->progress_rc;
1023 if (!rc)
1024 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_GENKEY, NULL);
1025 TEST_CANCEL();
1026 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
1028 pthread_cleanup_pop (1);
1031 if (!rc)
1033 gpgme_key_t *keys = NULL;
1034 char *p;
1035 char **pp;
1036 gpgme_genkey_result_t result;
1038 result = gpgme_op_genkey_result (crypto->ctx);
1039 p = str_dup (result->fpr);
1040 if (p)
1042 pp = strv_cat (crypto->save.sigkey, p);
1043 if (pp)
1045 crypto->save.sigkey = pp;
1046 crypto_keyid_to_16b (crypto->save.sigkey);
1048 else
1050 xfree (p);
1051 rc = GPG_ERR_ENOMEM;
1054 else
1055 rc = GPG_ERR_ENOMEM;
1057 if (!rc)
1058 rc = crypto_list_keys (crypto, crypto->save.sigkey, 1, &keys);
1060 if (!rc)
1062 gpgme_subkey_t key = keys[0]->subkeys;
1064 for (; key; key = key->next)
1066 if (key->can_encrypt)
1067 break;
1070 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
1071 rc = send_status (client ? client->ctx : NULL, STATUS_GENKEY, "%s %s",
1072 crypto->save.sigkey[0], key ? key->fpr : "");
1073 if (!rc)
1075 crypto->save.pubkey = strv_cat (crypto->save.pubkey,
1076 str_dup (key->fpr));
1077 crypto_keyid_to_16b (crypto->save.pubkey);
1080 pthread_cleanup_pop (1);
1084 return rc;
1087 char *
1088 crypto_default_key_params ()
1090 char *user = get_username (getuid());
1091 char *params = str_asprintf(
1092 "<GnupgKeyParms format=\"internal\">\n"
1093 " Key-Type: default\n"
1094 " Subkey-Type: default\n"
1095 " Name-Real: %s\n"
1096 " Name-Email: %s\n"
1097 " Expire-Date: 0\n"
1098 "</GnupgKeyParms>",
1099 getenv ("REALNAME") ? getenv ("REALNAME") : user,
1100 getenv ("EMAIL") ? getenv ("EMAIL") : user);
1102 xfree (user);
1103 return params;
1106 #ifdef WITH_LIBACL
1107 static void
1108 acl_free_cb (void *arg)
1110 acl_t acl = arg ? (acl_t) arg : NULL;
1112 if (acl)
1113 acl_free (acl);
1115 #endif
1117 /* The advisory lock should be obtained before calling this function. */
1118 gpg_error_t
1119 crypto_write_file (struct crypto_s *crypto)
1121 unsigned char *buf;
1122 size_t size, len;
1123 int fd;
1124 gpg_error_t rc;
1125 char tmp[PATH_MAX];
1126 struct stat st;
1127 mode_t mode = 0600;
1128 #ifdef WITH_LIBACL
1129 acl_t acl = NULL;
1130 #endif
1132 if (crypto->filename)
1134 if (lstat (crypto->filename, &st) == 0)
1136 mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
1138 if (!(mode & S_IWUSR))
1139 return GPG_ERR_EACCES;
1141 else if (errno != ENOENT)
1142 return gpg_error_from_errno (errno);
1144 snprintf (tmp, sizeof (tmp), "%s.XXXXXX", crypto->filename);
1145 mode_t tmode = umask (0600);
1146 fd = mkstemp (tmp);
1147 if (fd == -1)
1149 rc = gpg_error_from_errno (errno);
1150 umask (tmode);
1151 log_write ("%s: %s", tmp, pwmd_strerror (rc));
1152 return rc;
1155 umask (tmode);
1157 else
1158 fd = STDOUT_FILENO;
1160 rc = crypto_data_to_buf (crypto->cipher, &buf, &size);
1161 if (rc)
1163 if (crypto->filename)
1164 close (fd);
1165 return rc;
1168 pthread_cleanup_push ((void *)close_fd_cb, &fd);
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);
1175 if (!rc)
1177 if (fsync (fd) != -1)
1179 if (crypto->filename && close (fd) != -1)
1181 #ifdef WITH_LIBACL
1182 acl = acl_get_file (crypto->filename, ACL_TYPE_ACCESS);
1183 if (!acl && errno == ENOENT)
1184 acl = acl_get_file (".", ACL_TYPE_DEFAULT);
1185 if (!acl)
1186 log_write ("ACL: %s: %s", crypto->filename,
1187 pwmd_strerror (gpg_error_from_errno (errno)));
1188 pthread_cleanup_push ((void *)acl_free_cb, acl);
1189 #endif
1191 fd = -1;
1192 if (config_get_boolean (crypto->filename, "backup"))
1194 char tmp2[PATH_MAX];
1196 snprintf (tmp2, sizeof (tmp2), "%s.backup", crypto->filename);
1197 if (rename (crypto->filename, tmp2) == -1)
1198 if (errno != ENOENT)
1199 rc = gpg_error_from_errno (errno);
1202 if (!rc && rename (tmp, crypto->filename) == -1)
1203 rc = gpg_error_from_errno (errno);
1205 if (!rc)
1207 if (chmod (crypto->filename, mode) == -1)
1208 log_write ("%s(%u): %s", __FILE__, __LINE__,
1209 pwmd_strerror (gpg_error_from_syserror ()));
1211 #ifdef WITH_LIBACL
1212 if (!rc && acl && acl_set_file (crypto->filename,
1213 ACL_TYPE_ACCESS, acl))
1214 log_write ("ACL: %s: %s", crypto->filename,
1215 pwmd_strerror (gpg_error_from_errno (errno)));
1216 pthread_cleanup_pop (1);
1217 #endif
1219 else if (crypto->filename)
1220 rc = gpg_error_from_errno (errno);
1222 if (!rc && fd != -1)
1224 char *datadir = str_asprintf ("%s/data", homedir);
1226 if (datadir)
1228 int dfd = open (datadir, O_RDONLY);
1230 if (dfd != -1)
1232 if (fsync (dfd) == -1)
1233 log_write ("%s %d: %s", __FILE__, __LINE__,
1234 pwmd_strerror (errno));
1236 close (dfd);
1238 else
1239 log_write ("%s %d: %s", __FILE__, __LINE__,
1240 pwmd_strerror (errno));
1242 xfree (datadir);
1246 else
1247 rc = gpg_error_from_errno (errno);
1250 pthread_cleanup_pop (0); // close (fd)
1251 if (fd != -1)
1252 close (fd);
1253 return rc;
1256 char *
1257 crypto_key_info (const gpgme_key_t key)
1259 struct string_s *string = string_new (NULL), *s;
1260 char *line = NULL;
1261 unsigned n, u;
1262 gpgme_subkey_t subkey;
1263 gpgme_user_id_t uid;
1265 if (!string)
1266 return NULL;
1268 for (u = 0, uid = key->uids; uid; uid = uid->next)
1269 u++;
1271 for (n = 0, subkey = key->subkeys; subkey; subkey = subkey->next)
1272 n++;
1274 s = string_append_printf (string, "%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%i:%s:%s:%s:%i:%u:%u",
1275 key->revoked, key->expired, key->disabled,
1276 key->invalid, key->can_encrypt, key->can_sign,
1277 key->can_certify, key->secret,
1278 key->can_authenticate, key->is_qualified,
1279 key->protocol,
1280 key->issuer_serial ? key->issuer_serial : "",
1281 key->issuer_name ? key->issuer_name : "",
1282 key->chain_id ? key->chain_id : "",
1283 key->owner_trust, u, n);
1284 if (!s)
1286 string_free (string, 1);
1287 return NULL;
1290 string = s;
1291 for (subkey = key->subkeys; subkey; subkey = subkey->next)
1293 char *tmp;
1295 s = string_append_printf (string, ":%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%i:%u",
1296 subkey->revoked, subkey->expired,
1297 subkey->disabled, subkey->invalid,
1298 subkey->can_encrypt, subkey->can_sign,
1299 subkey->can_certify, subkey->secret,
1300 subkey->can_authenticate, subkey->is_qualified,
1301 subkey->is_cardkey, subkey->pubkey_algo,
1302 subkey->length);
1303 if (!s)
1305 string_free (string, 1);
1306 return NULL;
1309 string = s;
1310 s = string_append_printf (string, ":%s:%s:%s:%li:%li:%s",
1311 subkey->keyid, subkey->fpr,
1312 subkey->keygrip ? subkey->keygrip : "",
1313 subkey->timestamp, subkey->expires,
1314 subkey->card_number ? subkey->card_number : "0");
1315 if (!s)
1317 string_free (string, 1);
1318 return NULL;
1321 string = s;
1322 tmp = gnupg_escape (subkey->curve);
1323 s = string_append_printf (string, ":%s", tmp ? tmp : "");
1324 xfree (tmp);
1325 if (!s)
1327 string_free (string, 1);
1328 return NULL;
1331 string = s;
1334 for (uid = key->uids; uid; uid = uid->next)
1336 char *userid, *name, *email, *comment;
1338 userid = gnupg_escape (uid->uid);
1339 name = gnupg_escape (uid->name);
1340 email = gnupg_escape (uid->email);
1341 comment = gnupg_escape (uid->comment);
1342 s = string_append_printf (string, ":%u:%u:%u:%s:%s:%s:%s",
1343 uid->revoked, uid->invalid, uid->validity,
1344 userid ? userid : "",
1345 name ? name : "",
1346 email ? email : "",
1347 comment ? comment : "");
1348 xfree (userid);
1349 xfree (name);
1350 xfree (email);
1351 xfree (comment);
1352 if (!s)
1354 string_free (string, 1);
1355 return NULL;
1358 string = s;
1361 line = string->str;
1362 string_free (string, 0);
1363 return line;
1366 gpg_error_t
1367 crypto_try_decrypt (struct client_s *client, int no_pinentry)
1369 struct crypto_s *crypto;
1370 gpg_error_t rc;
1371 char *keyfile = config_get_string (client->filename, "passphrase_file");
1373 rc = crypto_init (&crypto, client->ctx, client->filename, no_pinentry,
1374 keyfile);
1375 if (!rc)
1377 pthread_cleanup_push ((void *)crypto_free, crypto);
1378 rc = crypto_decrypt (client, crypto);
1379 pthread_cleanup_pop (1);
1381 else
1382 xfree (keyfile);
1384 return rc;
1387 /* The advisory lock should be obtained before calling this function. */
1388 gpg_error_t
1389 crypto_is_symmetric (const char *filename)
1391 int fd;
1392 uint8_t magic[2];
1393 ssize_t len;
1395 fd = open (filename, O_RDONLY);
1396 if (fd == -1)
1397 return gpg_error_from_errno (errno);
1399 len = read (fd, &magic, sizeof(magic));
1400 close (fd);
1401 if (len != sizeof (magic))
1402 return GPG_ERR_INV_VALUE;
1404 // Always read as big endian.
1405 if (magic[0] != 0x8c || magic[1] != 0x0d)
1406 return GPG_ERR_BAD_DATA;
1408 return 0;