Add open_check_file() to replace open/[fl]stat.
[pwmd.git] / src / crypto.c
blob6c3e7fc4a7749b0d5296f2fe371a424a6dd5e3c4
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 /* 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 gpgme_error_t
272 crypto_list_keys (struct crypto_s *crypto, char *keys[], int secret,
273 gpgme_key_t **result)
275 gpgme_error_t rc;
276 gpgme_key_t key = NULL, *res = NULL;
277 size_t total = 0;
279 rc = gpgme_op_keylist_ext_start (crypto->ctx, (const char **)keys, secret, 0);
280 if (rc)
281 return rc;
283 STATUS_TIMEOUT_INIT (crypto);
286 gpgme_key_t *p;
288 pthread_cleanup_push ((void *)crypto_free_key_list, res);
289 rc = gpgme_op_keylist_next (crypto->ctx, &key);
290 pthread_cleanup_pop (0);
291 if (rc && gpgme_err_code(rc) != GPG_ERR_EOF)
292 break;
294 if (rc)
296 rc = 0;
297 break;
300 p = xrealloc (res, (total+2) * sizeof (gpgme_key_t));
301 if (!p)
303 rc = GPG_ERR_ENOMEM;
304 break;
307 res = p;
308 res[total++] = key;
309 res[total] = NULL;
310 pthread_cleanup_push ((void *)crypto_free_key_list, res);
311 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_KEEPALIVE, NULL);
312 pthread_cleanup_pop (0);
313 } while (!rc);
315 if (!rc)
317 rc = gpgme_op_keylist_end (crypto->ctx);
318 if (!rc)
320 *result = res;
321 rc = total ? 0 : secret ? GPG_ERR_NO_SECKEY : GPG_ERR_NO_PUBKEY;
324 else
325 crypto_free_key_list (res);
327 return rc;
330 void
331 crypto_free_save (struct save_s *save)
333 if (!save)
334 return;
336 strv_free (save->pubkey);
337 strv_free (save->sigkey);
338 memset (save, 0, sizeof (struct save_s));
341 static gpg_error_t
342 crypto_kill_scd ()
344 return cache_kill_scd ();
347 static void
348 free_gpgme_data_cb (void *data)
350 gpgme_data_t d = data;
351 char *t;
352 size_t len;
354 if (!data)
355 return;
357 t = gpgme_data_release_and_get_mem (d, &len);
358 if (t)
359 wipememory (t, 0, len);
361 gpgme_free (t);
364 void
365 crypto_free_non_keys (struct crypto_s *crypto)
367 if (!crypto)
368 return;
370 if (crypto->ctx)
371 gpgme_release (crypto->ctx);
373 crypto->ctx = NULL;
374 xfree (crypto->plaintext);
375 crypto->plaintext = NULL;
376 crypto->plaintext_size = 0;
378 if (crypto->cipher)
379 free_gpgme_data_cb (crypto->cipher);
381 crypto->cipher = NULL;
382 crypto_free_save (&crypto->save);
383 xfree (crypto->keyfile);
384 crypto->keyfile = NULL;
385 crypto->flags &= ~CRYPTO_FLAG_KEYFILE;
386 (void)crypto_kill_scd ();
389 void
390 crypto_free (struct crypto_s *crypto)
392 if (!crypto)
393 return;
395 crypto_free_non_keys (crypto);
396 strv_free (crypto->pubkey);
397 strv_free (crypto->sigkey);
398 xfree (crypto->filename);
399 xfree (crypto);
402 gpgme_error_t
403 crypto_init_ctx (struct crypto_s *crypto, int no_pinentry,
404 char *passphrase_file)
406 gpgme_ctx_t ctx;
407 gpgme_keylist_mode_t keylist_mode;
408 gpgme_error_t rc;
410 rc = gpgme_new (&ctx);
411 if (rc)
412 return rc;
414 rc = gpgme_set_protocol (ctx, GPGME_PROTOCOL_OPENPGP);
415 if (!rc)
417 keylist_mode = gpgme_get_keylist_mode (ctx);
418 keylist_mode |= GPGME_KEYLIST_MODE_LOCAL|GPGME_KEYLIST_MODE_WITH_SECRET;
419 rc = gpgme_set_keylist_mode (ctx, keylist_mode);
420 if (!rc)
422 if (no_pinentry || passphrase_file)
423 rc = gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_LOOPBACK);
424 else
425 rc = gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_DEFAULT);
427 if (!rc)
429 gpgme_set_passphrase_cb (ctx, passphrase_cb, crypto);
430 gpgme_set_progress_cb (ctx, progress_cb, crypto);
431 gpgme_set_status_cb (ctx, status_cb, crypto);
432 crypto->ctx = ctx;
433 crypto->flags = 0;
436 if (passphrase_file)
438 crypto->keyfile = passphrase_file;
439 crypto->flags |= CRYPTO_FLAG_KEYFILE;
444 if (rc)
445 gpgme_release (ctx);
447 return rc;
450 void
451 crypto_set_keepalive ()
453 keepalive = config_get_integer ("global", "keepalive_interval");
456 gpg_error_t
457 crypto_init (struct crypto_s **crypto, void *ctx, const char *filename,
458 int no_pinentry, char *passphrase_file)
460 struct crypto_s *new = xcalloc (1, sizeof (struct crypto_s));
461 gpgme_error_t rc;
463 crypto_set_keepalive ();
465 if (!new)
466 return GPG_ERR_ENOMEM;
468 rc = crypto_init_ctx (new, no_pinentry, passphrase_file);
469 if (rc)
470 goto fail;
472 if (filename)
474 new->filename = str_dup (filename);
475 if (!new->filename)
477 rc = GPG_ERR_ENOMEM;
478 goto fail;
482 new->client_ctx = ctx;
483 *crypto = new;
484 return 0;
486 fail:
487 crypto_free (new);
488 return rc;
491 /* Converts a 40 byte key id to the 16 byte form. Needed for comparison of
492 * gpgme_recipient_t.keyid. */
493 gpg_error_t
494 crypto_keyid_to_16b (char **keys)
496 char **p;
498 for (p = keys; p && *p; p++)
500 char *t = *p;
501 size_t len = strlen (t);
503 if (len < 16)
504 return GPG_ERR_INV_ARG;
506 memmove (&t[0], &t[len-16], 16);
507 t[16] = 0;
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;
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);
611 for (s = verify->signatures; s; s = s->next)
613 pthread_cleanup_push ((void *)strv_free, new_signers);
614 log_write1 (_ ("%s: signer: %s, status=%u"),
615 crypto->filename, s->fpr, s->status);
616 pthread_cleanup_pop (0);
617 if (s->status || s->wrong_key_usage
618 || !(s->summary & GPGME_SIGSUM_VALID))
619 continue;
621 pp = strv_cat (new_signers, str_dup (s->fpr));
622 if (!pp)
624 rc = GPG_ERR_ENOMEM;
625 break;
628 new_signers = pp;
631 if (verify->signatures && !new_signers)
632 rc = GPG_ERR_BAD_SIGNATURE;
634 if (!rc)
636 xfree (crypto->plaintext);
637 crypto->plaintext = NULL;
638 crypto->plaintext_size = 0;
639 pthread_cleanup_push ((void *)strv_free, new_recipients);
640 pthread_cleanup_push ((void *)strv_free, new_signers);
641 rc = crypto_data_to_buf (plain, &crypto->plaintext,
642 &crypto->plaintext_size);
643 pthread_cleanup_pop (0);
644 pthread_cleanup_pop (0);
645 if (!rc)
647 strv_free (crypto->pubkey);
648 crypto->pubkey = new_recipients;
649 crypto_keyid_to_16b (crypto->pubkey);
650 strv_free (crypto->sigkey);
651 crypto->sigkey = new_signers;
652 crypto_keyid_to_16b (crypto->sigkey);
657 if (rc)
659 strv_free (new_recipients);
660 strv_free (new_signers);
663 pthread_cleanup_pop (1); // free_gpgme_data_cb (plain)
664 return rc;
667 void
668 crypto_free_key_list (gpgme_key_t *keys)
670 int i;
672 for (i = 0; keys && keys[i]; i++)
673 gpgme_key_unref (keys[i]);
675 xfree (keys);
678 /* Removes strings in 'prune' from 'a'. */
679 static char **
680 prune_keys (char **a, char **prune)
682 char **p;
684 for (p = prune; p && *p; p++)
686 char **ap;
688 for (ap = a; ap && *ap; ap++)
690 if (!strcmp (*ap, *p))
692 while (*ap)
694 *ap = *(ap+1);
695 ap++;
701 return a;
704 static void
705 remove_duplicates (char **a)
707 char **p;
709 for (p = a; p && *p; p++)
711 char **t;
713 for (t = p+1; t && *t; t++)
715 if (!strcmp (*p, *t))
717 char *tmp = *t;
719 while (*(t+1))
721 *t = *(t+1);
722 t++;
725 *t = NULL;
726 xfree (tmp);
727 remove_duplicates (a);
728 return;
734 gpgme_error_t
735 crypto_encrypt (struct client_s *client, struct crypto_s *crypto)
737 gpgme_error_t rc;
738 gpgme_data_t cipher = NULL;
739 gpgme_key_t *keys = NULL;
740 gpgme_key_t *sigkeys = NULL;
741 unsigned flags = 0;
742 int sign = 0;
744 if (!(crypto->flags & CRYPTO_FLAG_SYMMETRIC))
746 crypto_keyid_to_16b (crypto->save.pubkey);
747 remove_duplicates (crypto->save.pubkey);
748 rc = crypto_list_keys (crypto, crypto->save.pubkey, 0, &keys);
749 if (rc)
750 return rc;
753 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
754 rc = gpgme_data_new (&cipher);
755 pthread_cleanup_push ((void *)free_gpgme_data_cb, cipher);
756 if (!rc)
757 rc = gpgme_data_set_file_name (cipher, crypto->filename);
759 if (!rc && (crypto->save.sigkey
760 || !(crypto->flags & CRYPTO_FLAG_SYMMETRIC)))
762 crypto_keyid_to_16b (crypto->save.sigkey);
763 remove_duplicates (crypto->save.sigkey);
764 rc = crypto_list_keys (crypto, crypto->save.sigkey, 1, &sigkeys);
765 if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
766 rc = 0;
769 if (!rc)
771 gpgme_data_t plain = NULL;
773 pthread_cleanup_push ((void *)crypto_free_key_list, sigkeys);
774 rc = gpgme_data_new_from_mem (&plain, (char *)crypto->plaintext,
775 crypto->plaintext_size, 0);
776 pthread_cleanup_push ((void *)free_gpgme_data_cb, plain);
777 if (!rc)
779 int i;
781 gpgme_signers_clear (crypto->ctx);
783 for (i = 0; sigkeys && sigkeys[i]; i++)
784 gpgme_signers_add (crypto->ctx, sigkeys[i]);
786 if (!i && !(crypto->flags & CRYPTO_FLAG_SYMMETRIC))
787 rc = GPG_ERR_NO_SIGNATURE_SCHEME;
790 if (!rc)
792 gpgme_data_set_encoding (cipher, GPGME_DATA_ENCODING_ARMOR);
793 rc = send_status (client ? client->ctx : NULL, STATUS_ENCRYPT, NULL);
796 if (!rc)
798 int f = config_get_boolean ("global", "encrypt_to");
800 if (!f)
801 flags |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
803 f = config_get_boolean ("global", "always_trust");
804 if (f)
805 flags |= GPGME_ENCRYPT_ALWAYS_TRUST;
807 if (!(crypto->flags & CRYPTO_FLAG_SYMMETRIC)
808 || (crypto->flags & CRYPTO_FLAG_SYMMETRIC && sigkeys))
809 sign = 1;
812 if (!rc)
813 MUTEX_TRYLOCK (client->ctx, &crypto_mutex, rc, client->lock_timeout);
815 if (!rc)
817 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
818 if (sign)
819 rc = gpgme_op_encrypt_sign_start (crypto->ctx, keys, flags, plain,
820 cipher);
821 else
822 rc = gpgme_op_encrypt_start (crypto->ctx, NULL, flags, plain,
823 cipher);
824 if (!rc)
826 STATUS_TIMEOUT_INIT (crypto);
829 if (!rc && crypto->progress_rc)
830 rc = crypto->progress_rc;
831 if (!rc)
832 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_ENCRYPT, NULL);
833 TEST_CANCEL();
834 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
836 pthread_cleanup_pop (1);
838 if (!rc)
840 gpgme_encrypt_result_t result;
841 gpgme_sign_result_t sresult;
842 gpgme_invalid_key_t inv;
843 gpgme_new_signature_t sigs;
844 char **prune = NULL;
845 char **p = NULL;
847 result = gpgme_op_encrypt_result (crypto->ctx);
848 inv = result->invalid_recipients;
849 while (inv)
851 pthread_cleanup_push ((void *)strv_free, prune);
852 log_write1 (_ ("%s: invalid recipient: %s, rc=%u"),
853 crypto->filename, inv->fpr, inv->reason);
854 pthread_cleanup_pop (0);
855 p = strv_cat (prune, str_dup(inv->fpr));
856 if (!p)
858 rc = GPG_ERR_ENOMEM;
859 strv_free (prune);
860 break;
863 prune = p;
864 inv = inv->next;
867 if (prune)
869 p = prune_keys (crypto->save.pubkey, prune);
870 crypto->save.pubkey = p;
871 strv_free (prune);
874 crypto_keyid_to_16b (crypto->save.pubkey);
875 sresult = gpgme_op_sign_result (crypto->ctx);
876 inv = sresult ? sresult->invalid_signers : NULL;
877 while (!rc && inv)
879 log_write1 (_ ("%s: invalid signer: %s, rc=%u"),
880 crypto->filename, inv->fpr, inv->reason);
881 inv = inv->next;
884 sigs = sresult ? sresult->signatures : NULL;
885 if (!rc && sigs)
887 p = NULL;
889 while (sigs)
891 char **pp;
893 pthread_cleanup_push ((void *)strv_free, p);
894 log_write1 (_ ("%s: signer: %s"), crypto->filename,
895 sigs->fpr);
896 pthread_cleanup_pop (0);
898 pp = strv_cat (p, str_dup (sigs->fpr));
899 if (!pp)
901 rc = GPG_ERR_ENOMEM;
902 strv_free (p);
903 break;
906 p = pp;
907 sigs = sigs->next;
910 if (!rc)
912 strv_free (crypto->save.sigkey);
913 crypto->save.sigkey = p;
914 crypto_keyid_to_16b (crypto->save.sigkey);
915 crypto->cipher = cipher;
918 else if (!rc && crypto->flags & CRYPTO_FLAG_SYMMETRIC)
920 crypto->cipher = cipher;
922 else if (!rc)
924 if (!(crypto->flags & CRYPTO_FLAG_SYMMETRIC)
925 || (crypto->flags & CRYPTO_FLAG_SYMMETRIC && sigkeys))
926 rc = GPG_ERR_NO_SIGNATURE_SCHEME;
931 pthread_cleanup_pop (1); // free_gpgme_data_cb (plain)
932 pthread_cleanup_pop (1); // crypto_free_key_list (sigkeys)
935 pthread_cleanup_pop (0); // free_gpgme_data_cb (cipher)
936 pthread_cleanup_pop (1); // crypto_free_key_list (keys)
938 if (rc)
939 free_gpgme_data_cb (cipher);
941 return rc;
944 gpgme_error_t
945 crypto_passwd (struct client_s *client, struct crypto_s *crypto)
947 gpgme_error_t rc;
948 gpgme_key_t *keys = NULL;
950 /* Use SAVE instead for symmetric files. */
951 rc = crypto_is_symmetric (client->filename);
952 if (!rc || rc != GPG_ERR_BAD_DATA)
953 return !rc ? GPG_ERR_NOT_SUPPORTED : rc;
955 rc = crypto_list_keys (crypto, crypto->pubkey, 1, &keys);
956 if (rc)
957 return rc;
959 crypto->flags |= CRYPTO_FLAG_PASSWD;
960 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
961 rc = send_status (client->ctx, STATUS_KEEPALIVE, NULL);
962 if (!rc)
963 MUTEX_TRYLOCK (client->ctx, &crypto_mutex, rc, client->lock_timeout);
965 if (!rc)
967 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
968 rc = gpgme_op_passwd_start (crypto->ctx, keys[0], 0);
969 if (!rc)
971 STATUS_TIMEOUT_INIT (crypto);
974 if (!rc && crypto->progress_rc)
975 rc = crypto->progress_rc;
976 if (!rc)
977 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_KEEPALIVE, NULL);
978 TEST_CANCEL();
979 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
981 pthread_cleanup_pop (1);
984 pthread_cleanup_pop (1);
985 return rc;
988 /* Generate a new key pair. The resulting keyid's are stored in crypto->save.
990 gpgme_error_t
991 crypto_genkey (struct client_s *client, struct crypto_s *crypto,
992 const unsigned char *params)
994 gpgme_error_t rc;
996 if (strstr ((char *) params, "%pubring")
997 || strstr ((char *) params, "%secring"))
998 return GPG_ERR_INV_VALUE;
1000 rc = send_status (client ? client->ctx : NULL, STATUS_GENKEY, NULL);
1001 if (!rc)
1002 MUTEX_TRYLOCK (client->ctx, &crypto_mutex, rc, client->lock_timeout);
1004 if (!rc)
1006 pthread_cleanup_push (release_mutex_cb, &crypto_mutex);
1007 rc = gpgme_op_genkey_start (crypto->ctx, (const char *)params, NULL, NULL);
1008 if (!rc)
1010 STATUS_TIMEOUT_INIT (crypto);
1013 if (!rc && crypto->progress_rc)
1014 rc = crypto->progress_rc;
1015 if (!rc)
1016 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_GENKEY, NULL);
1017 TEST_CANCEL();
1018 } while (!rc && !gpgme_wait (crypto->ctx, &rc, 0) && !rc);
1020 pthread_cleanup_pop (1);
1023 if (!rc)
1025 gpgme_key_t *keys = NULL;
1026 char *p;
1027 char **pp;
1028 gpgme_genkey_result_t result;
1030 result = gpgme_op_genkey_result (crypto->ctx);
1031 p = str_dup (result->fpr);
1032 if (p)
1034 pp = strv_cat (crypto->save.sigkey, p);
1035 if (pp)
1037 crypto->save.sigkey = pp;
1038 crypto_keyid_to_16b (crypto->save.sigkey);
1040 else
1042 xfree (p);
1043 rc = GPG_ERR_ENOMEM;
1046 else
1047 rc = GPG_ERR_ENOMEM;
1049 if (!rc)
1050 rc = crypto_list_keys (crypto, crypto->save.sigkey, 1, &keys);
1052 if (!rc)
1054 gpgme_subkey_t key = keys[0]->subkeys;
1056 for (; key; key = key->next)
1058 if (key->can_encrypt)
1059 break;
1062 pthread_cleanup_push ((void *)crypto_free_key_list, keys);
1063 rc = send_status (client ? client->ctx : NULL, STATUS_GENKEY, "%s %s",
1064 crypto->save.sigkey[0], key ? key->fpr : "");
1065 if (!rc)
1067 crypto->save.pubkey = strv_cat (crypto->save.pubkey,
1068 str_dup (key->fpr));
1069 crypto_keyid_to_16b (crypto->save.pubkey);
1072 pthread_cleanup_pop (1);
1076 return rc;
1079 char *
1080 crypto_default_key_params ()
1082 char *user = get_username (getuid());
1083 char *params = str_asprintf(
1084 "<GnupgKeyParms format=\"internal\">\n"
1085 " Key-Type: default\n"
1086 " Subkey-Type: default\n"
1087 " Name-Real: %s\n"
1088 " Name-Email: %s\n"
1089 " Expire-Date: 0\n"
1090 "</GnupgKeyParms>",
1091 getenv ("REALNAME") ? getenv ("REALNAME") : user,
1092 getenv ("EMAIL") ? getenv ("EMAIL") : user);
1094 xfree (user);
1095 return params;
1098 #ifdef WITH_LIBACL
1099 static void
1100 acl_free_cb (void *arg)
1102 acl_t acl = arg ? (acl_t) arg : NULL;
1104 if (acl)
1105 acl_free (acl);
1107 #endif
1109 /* The advisory lock should be obtained before calling this function. */
1110 gpg_error_t
1111 crypto_write_file (struct crypto_s *crypto)
1113 unsigned char *buf;
1114 size_t size, len;
1115 int fd;
1116 gpg_error_t rc;
1117 char tmp[PATH_MAX];
1118 struct stat st;
1119 mode_t mode = 0600;
1120 #ifdef WITH_LIBACL
1121 acl_t acl = NULL;
1122 #endif
1124 if (crypto->filename)
1126 if (lstat (crypto->filename, &st) == 0)
1128 mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
1130 if (!(mode & S_IWUSR))
1131 return GPG_ERR_EACCES;
1133 else if (errno != ENOENT)
1134 return gpg_error_from_errno (errno);
1136 snprintf (tmp, sizeof (tmp), "%s.XXXXXX", crypto->filename);
1137 mode_t tmode = umask (0600);
1138 fd = mkstemp (tmp);
1139 if (fd == -1)
1141 rc = gpg_error_from_errno (errno);
1142 umask (tmode);
1143 log_write ("%s: %s", tmp, pwmd_strerror (rc));
1144 return rc;
1147 umask (tmode);
1149 else
1150 fd = STDOUT_FILENO;
1152 rc = crypto_data_to_buf (crypto->cipher, &buf, &size);
1153 if (rc)
1155 if (crypto->filename)
1156 close (fd);
1157 return rc;
1160 pthread_cleanup_push ((void *)close_fd_cb, &fd);
1161 pthread_cleanup_push ((void *)xfree, buf);
1162 len = write (fd, buf, size);
1163 pthread_cleanup_pop (1);
1164 if (len != size)
1165 rc = gpg_error_from_errno (errno);
1167 if (!rc)
1169 if (fsync (fd) != -1)
1171 if (crypto->filename && close (fd) != -1)
1173 #ifdef WITH_LIBACL
1174 acl = acl_get_file (crypto->filename, ACL_TYPE_ACCESS);
1175 if (!acl && errno == ENOENT)
1176 acl = acl_get_file (".", ACL_TYPE_DEFAULT);
1177 if (!acl)
1178 log_write ("ACL: %s: %s", crypto->filename,
1179 pwmd_strerror (gpg_error_from_errno (errno)));
1180 pthread_cleanup_push ((void *)acl_free_cb, acl);
1181 #endif
1183 fd = -1;
1184 if (config_get_boolean (crypto->filename, "backup"))
1186 char tmp2[PATH_MAX];
1188 snprintf (tmp2, sizeof (tmp2), "%s.backup", crypto->filename);
1189 if (rename (crypto->filename, tmp2) == -1)
1190 if (errno != ENOENT)
1191 rc = gpg_error_from_errno (errno);
1194 if (!rc && rename (tmp, crypto->filename) == -1)
1195 rc = gpg_error_from_errno (errno);
1197 if (!rc)
1199 if (chmod (crypto->filename, mode) == -1)
1200 log_write ("%s(%u): %s", __FILE__, __LINE__,
1201 pwmd_strerror (gpg_error_from_syserror ()));
1203 #ifdef WITH_LIBACL
1204 if (!rc && acl && acl_set_file (crypto->filename,
1205 ACL_TYPE_ACCESS, acl))
1206 log_write ("ACL: %s: %s", crypto->filename,
1207 pwmd_strerror (gpg_error_from_errno (errno)));
1208 pthread_cleanup_pop (1);
1209 #endif
1211 else if (crypto->filename)
1212 rc = gpg_error_from_errno (errno);
1214 if (!rc && fd != -1)
1216 char *datadir = str_asprintf ("%s/data", homedir);
1218 if (datadir)
1220 int dfd = open (datadir, O_RDONLY);
1222 if (dfd != -1)
1224 if (fsync (dfd) == -1)
1225 log_write ("%s %d: %s", __FILE__, __LINE__,
1226 pwmd_strerror (errno));
1228 close (dfd);
1230 else
1231 log_write ("%s %d: %s", __FILE__, __LINE__,
1232 pwmd_strerror (errno));
1234 xfree (datadir);
1238 else
1239 rc = gpg_error_from_errno (errno);
1242 pthread_cleanup_pop (0); // close (fd)
1243 if (fd != -1)
1244 close (fd);
1245 return rc;
1248 char *
1249 crypto_key_info (const gpgme_key_t key)
1251 struct string_s *string = string_new (NULL), *s;
1252 char *line = NULL;
1253 unsigned n, u;
1254 gpgme_subkey_t subkey;
1255 gpgme_user_id_t uid;
1257 if (!string)
1258 return NULL;
1260 for (u = 0, uid = key->uids; uid; uid = uid->next)
1261 u++;
1263 for (n = 0, subkey = key->subkeys; subkey; subkey = subkey->next)
1264 n++;
1266 s = string_append_printf (string, "%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%i:%s:%s:%s:%i:%u:%u",
1267 key->revoked, key->expired, key->disabled,
1268 key->invalid, key->can_encrypt, key->can_sign,
1269 key->can_certify, key->secret,
1270 key->can_authenticate, key->is_qualified,
1271 key->protocol,
1272 key->issuer_serial ? key->issuer_serial : "",
1273 key->issuer_name ? key->issuer_name : "",
1274 key->chain_id ? key->chain_id : "",
1275 key->owner_trust, u, n);
1276 if (!s)
1278 string_free (string, 1);
1279 return NULL;
1282 string = s;
1283 for (subkey = key->subkeys; subkey; subkey = subkey->next)
1285 char *tmp;
1287 s = string_append_printf (string, ":%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%i:%u",
1288 subkey->revoked, subkey->expired,
1289 subkey->disabled, subkey->invalid,
1290 subkey->can_encrypt, subkey->can_sign,
1291 subkey->can_certify, subkey->secret,
1292 subkey->can_authenticate, subkey->is_qualified,
1293 subkey->is_cardkey, subkey->pubkey_algo,
1294 subkey->length);
1295 if (!s)
1297 string_free (string, 1);
1298 return NULL;
1301 string = s;
1302 s = string_append_printf (string, ":%s:%s:%s:%li:%li:%s",
1303 subkey->keyid, subkey->fpr,
1304 subkey->keygrip ? subkey->keygrip : "",
1305 subkey->timestamp, subkey->expires,
1306 subkey->card_number ? subkey->card_number : "0");
1307 if (!s)
1309 string_free (string, 1);
1310 return NULL;
1313 string = s;
1314 tmp = gnupg_escape (subkey->curve);
1315 s = string_append_printf (string, ":%s", tmp ? tmp : "");
1316 xfree (tmp);
1317 if (!s)
1319 string_free (string, 1);
1320 return NULL;
1323 string = s;
1326 for (uid = key->uids; uid; uid = uid->next)
1328 char *userid, *name, *email, *comment;
1330 userid = gnupg_escape (uid->uid);
1331 name = gnupg_escape (uid->name);
1332 email = gnupg_escape (uid->email);
1333 comment = gnupg_escape (uid->comment);
1334 s = string_append_printf (string, ":%u:%u:%u:%s:%s:%s:%s",
1335 uid->revoked, uid->invalid, uid->validity,
1336 userid ? userid : "",
1337 name ? name : "",
1338 email ? email : "",
1339 comment ? comment : "");
1340 xfree (userid);
1341 xfree (name);
1342 xfree (email);
1343 xfree (comment);
1344 if (!s)
1346 string_free (string, 1);
1347 return NULL;
1350 string = s;
1353 line = string->str;
1354 string_free (string, 0);
1355 return line;
1358 gpg_error_t
1359 crypto_try_decrypt (struct client_s *client, int no_pinentry)
1361 struct crypto_s *crypto;
1362 gpg_error_t rc;
1363 char *keyfile = config_get_string (client->filename, "passphrase_file");
1365 rc = crypto_init (&crypto, client->ctx, client->filename, no_pinentry,
1366 keyfile);
1367 if (!rc)
1369 pthread_cleanup_push ((void *)crypto_free, crypto);
1370 rc = crypto_decrypt (client, crypto);
1371 pthread_cleanup_pop (1);
1373 else
1374 xfree (keyfile);
1376 return rc;
1379 /* The advisory lock should be obtained before calling this function. */
1380 gpg_error_t
1381 crypto_is_symmetric (const char *filename)
1383 int fd;
1384 uint8_t magic[2];
1385 ssize_t len;
1386 gpg_error_t rc;
1388 rc = open_check_file (filename, &fd, NULL, 1);
1389 if (rc)
1390 return rc;
1392 len = read (fd, &magic, sizeof(magic));
1393 close (fd);
1394 if (len != sizeof (magic))
1395 return GPG_ERR_INV_VALUE;
1397 // Always read as big endian.
1398 if (magic[0] != 0x8c || magic[1] != 0x0d)
1399 return GPG_ERR_BAD_DATA;
1401 return 0;