Return GPG_ERR_NO_PUB/SECKEY from LISTKEYS.
[libpwmd.git] / src / crypto.c
blobe1e16487f5cf5af481c5dfb4e766a440133146a0
1 /*
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014
3 Ben Kibbey <bjk@luxsci.net>
5 This file is part of pwmd.
7 Pwmd is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 2 of the License, or
10 (at your option) any later version.
12 Pwmd is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Pwmd. If not, see <http://www.gnu.org/licenses/>.
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
24 #include <stdio.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <errno.h>
30 #include "pwmd-error.h"
31 #include "util-misc.h"
32 #include "common.h"
33 #include "rcfile.h"
34 #include "crypto.h"
35 #include "cache.h"
36 #include "mem.h"
37 #include "util-string.h"
38 #include "rcfile.h"
40 static int keepalive;
42 #define BUFSIZE 4096
44 #define STATUS_TIMEOUT_INIT(crypto) \
45 do { \
46 crypto->status_timeout = time (NULL); \
47 crypto->progress_rc = 0; \
48 } while (0)
50 #define STATUS_TIMEOUT_TEST(crypto, rc, s, line) \
51 do { \
52 time_t now = time (NULL); \
53 if (now - crypto->status_timeout >= keepalive && crypto->client_ctx) { \
54 rc = send_status (crypto->client_ctx, s, line); \
55 crypto->status_timeout = now; \
56 } \
57 } while (0)
59 #if 0
60 static gpgme_error_t
61 show_key_output (gpgme_key_t key)
63 gpgme_subkey_t keyp; // first is primary
65 for (keyp = key->subkeys; keyp; keyp = keyp->next)
67 fprintf(stderr, "keyid: %s, revoked: %i, expired: %i, disabled: %i, invalid: %i,"
68 "encrypt: %i, sign: %i, cert: %i, auth: %i, secret: %i\n",
69 keyp->keyid, keyp->revoked, keyp->expired, keyp->disabled,
70 keyp->invalid, keyp->can_encrypt, keyp->can_sign,
71 keyp->can_certify, keyp->can_authenticate, keyp->secret);
74 return 0;
76 #endif
78 static gpgme_error_t
79 passphrase_cb (void *data, const char *hint, const char *info, int bad, int fd)
81 struct crypto_s *crypto = data;
82 unsigned char *result = NULL;
83 size_t len;
84 gpg_error_t rc = GPG_ERR_CANCELED;
86 if (hint)
87 rc = assuan_write_status (crypto->client_ctx, "PASSPHRASE_HINT", hint);
89 if (!rc && info)
90 rc = assuan_write_status (crypto->client_ctx, "PASSPHRASE_INFO", info);
92 if (!rc)
93 rc = assuan_inquire (crypto->client_ctx, "PASSPHRASE", &result, &len, 0);
95 if (!rc)
97 if (!result || !*result)
98 gpgme_io_writen (fd, "\n", 1);
99 else
101 int nl = result[len-1] == '\n';
102 int ret;
104 ret = gpgme_io_writen (fd, result, len);
105 if (!ret && !nl)
106 gpgme_io_writen (fd, "\n", 1);
107 else if (ret)
108 rc = GPG_ERR_CANCELED;
112 xfree (result);
113 return rc;
116 static void
117 progress_cb (void *data, const char *what, int type, int current, int total)
119 struct crypto_s *crypto = data;
121 crypto->progress_rc = send_status (crypto->client_ctx, STATUS_GPGME,
122 "%s %i %i %i", what, type, current, total);
125 gpgme_error_t
126 crypto_data_to_buf (const gpgme_data_t data, unsigned char **result,
127 size_t *rlen)
129 gpgme_error_t rc = gpgme_data_seek (data, 0, SEEK_SET);
130 ssize_t ret;
131 size_t total = 0, size = BUFSIZE;
132 unsigned char *buf;
134 if (rc)
135 return rc;
137 buf = xmalloc (size);
138 if (!buf)
139 return GPG_ERR_ENOMEM;
143 ret = gpgme_data_read (data, &buf[total], BUFSIZE);
144 if (ret > 0)
146 unsigned char *p;
148 total += ret;
149 size += BUFSIZE;
150 p = xrealloc (buf, size * sizeof(char));
151 if (!p)
153 xfree (buf);
154 return GPG_ERR_ENOMEM;
157 buf = p;
159 } while (ret > 0);
161 if (ret == -1)
163 rc = gpgme_err_code_from_syserror ();
164 xfree (buf);
165 return rc;
168 *result = buf;
169 *rlen = total;
170 return 0;
173 gpgme_error_t
174 crypto_list_keys (struct crypto_s *crypto, char *keys[], int secret,
175 gpgme_key_t **result)
177 gpgme_error_t rc;
178 gpgme_key_t key = NULL, *res = NULL;
179 size_t total = 0;
181 STATUS_TIMEOUT_INIT (crypto);
182 rc = gpgme_op_keylist_ext_start (crypto->ctx, (const char **)keys, secret, 0);
183 if (rc)
184 return rc;
188 gpgme_key_t *p;
190 rc = gpgme_op_keylist_next (crypto->ctx, &key);
191 if (rc && gpgme_err_code(rc) != GPG_ERR_EOF)
192 break;
194 if (rc)
196 rc = 0;
197 break;
200 p = xrealloc (res, (total+2) * sizeof (gpgme_key_t *));
201 if (!p)
203 rc = GPG_ERR_ENOMEM;
204 break;
207 res = p;
208 res[total++] = key;
209 res[total] = NULL;
210 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_GPGME, NULL);
211 } while (!rc);
213 if (!rc)
215 rc = gpgme_op_keylist_end (crypto->ctx);
216 if (!rc)
218 *result = res;
219 rc = total ? 0 : secret ? GPG_ERR_NO_SECKEY : GPG_ERR_NO_PUBKEY;
222 else
223 crypto_free_key_list (res);
225 return rc;
228 void
229 crypto_cleanup_save (struct save_s *save)
231 if (!save)
232 return;
234 strv_free (save->pubkey);
235 strv_free (save->sigkey);
236 memset (save, 0, sizeof (struct save_s));
239 void
240 crypto_cleanup_non_keys (struct crypto_s *crypto)
242 if (!crypto)
243 return;
245 if (crypto->ctx)
246 gpgme_release (crypto->ctx);
248 crypto->ctx = NULL;
249 xfree (crypto->plaintext);
250 crypto->plaintext = NULL;
251 crypto->plaintext_size = 0;
253 if (crypto->cipher)
254 gpgme_data_release (crypto->cipher);
256 crypto->cipher = NULL;
257 crypto_cleanup_save (&crypto->save);
260 void
261 crypto_cleanup (struct crypto_s *crypto)
263 if (!crypto)
264 return;
266 crypto_cleanup_non_keys (crypto);
267 strv_free (crypto->pubkey);
268 strv_free (crypto->sigkey);
269 xfree (crypto->filename);
270 xfree (crypto);
273 gpgme_error_t
274 crypto_init_ctx (struct crypto_s *crypto, int no_pinentry)
276 gpgme_ctx_t ctx;
277 gpgme_keylist_mode_t keylist_mode;
278 gpgme_error_t rc;
280 rc = gpgme_new (&ctx);
281 if (rc)
282 return rc;
284 rc = gpgme_set_protocol (ctx, GPGME_PROTOCOL_OPENPGP);
285 if (!rc)
287 keylist_mode = gpgme_get_keylist_mode (ctx);
288 keylist_mode |= GPGME_KEYLIST_MODE_LOCAL|GPGME_KEYLIST_MODE_WITH_SECRET;
289 rc = gpgme_set_keylist_mode (ctx, keylist_mode);
290 if (!rc)
292 if (no_pinentry)
293 rc = gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_LOOPBACK);
294 else
295 rc = gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_DEFAULT);
297 gpgme_set_passphrase_cb (ctx, passphrase_cb, crypto);
298 gpgme_set_progress_cb (ctx, progress_cb, crypto);
299 crypto->ctx = ctx;
303 if (rc)
304 gpgme_release (ctx);
306 return rc;
309 gpg_error_t
310 crypto_init (struct crypto_s **crypto, void *ctx, const char *filename,
311 int no_pinentry)
313 struct crypto_s *new = xcalloc (1, sizeof (struct crypto_s));
314 gpgme_error_t rc;
316 keepalive = config_get_integer ("global", "keepalive_interval");
318 if (!new)
319 return GPG_ERR_ENOMEM;
321 rc = crypto_init_ctx (new, no_pinentry);
322 if (rc)
323 goto fail;
325 if (filename)
327 new->filename = str_dup (filename);
328 if (!new->filename)
329 goto fail;
332 new->client_ctx = ctx;
333 *crypto = new;
334 return 0;
336 fail:
337 crypto_cleanup (new);
338 return rc;
341 gpgme_error_t
342 crypto_decrypt (struct client_s *client, struct crypto_s *crypto)
344 gpgme_data_t plain;
345 gpgme_error_t rc;
346 gpgme_data_t cipher;
347 int fd;
349 rc = gpgme_data_new (&plain);
350 if (rc)
351 return rc;
353 fd = open (crypto->filename, O_RDONLY);
354 if (fd == -1)
355 return gpgme_err_code_from_syserror ();
357 rc = gpgme_data_new_from_fd (&cipher, fd);
358 if (rc)
360 close (fd);
361 return rc;
364 STATUS_TIMEOUT_INIT(crypto);
365 rc = send_status (client ? client->ctx : NULL, STATUS_DECRYPT, NULL);
366 if (!rc)
367 rc = gpgme_op_decrypt_verify_start (crypto->ctx, cipher, plain);
369 if (rc)
371 close (fd);
372 gpgme_data_release (cipher);
373 return rc;
378 if (!rc && crypto->progress_rc)
379 rc = crypto->progress_rc;
381 if (!rc)
382 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_DECRYPT, NULL);
384 if (rc)
385 break;
386 } while (!gpgme_wait (crypto->ctx, &rc, 0) && !rc);
388 gpgme_data_release (cipher);
389 close (fd);
391 if (!rc)
393 char **pp;
394 gpgme_decrypt_result_t result;
396 result = gpgme_op_decrypt_result (crypto->ctx);
397 if (!result->unsupported_algorithm && !result->wrong_key_usage)
399 gpgme_recipient_t r;
401 strv_free (crypto->pubkey);
402 crypto->pubkey = NULL;
404 for (r = result->recipients; r; r = r->next)
406 log_write (_ ("%s: recipient: %s, status=%u"),
407 crypto->filename, r->keyid, r->status);
409 pp = strv_cat(crypto->pubkey, str_dup (r->keyid));
410 if (!pp)
412 rc = GPG_ERR_ENOMEM;
413 break;
416 crypto->pubkey = pp;
419 else if (result->wrong_key_usage)
420 rc = GPG_ERR_WRONG_KEY_USAGE;
421 else if (result->unsupported_algorithm)
422 rc = GPG_ERR_UNSUPPORTED_ALGORITHM;
424 if (!rc)
426 gpgme_verify_result_t result;
427 gpgme_signature_t s;
429 strv_free (crypto->sigkey);
430 crypto->sigkey = NULL;
431 result = gpgme_op_verify_result (crypto->ctx);
433 for (s = result->signatures; s; s = s->next)
435 log_write (_ ("%s: signer: %s, status=%u"),
436 crypto->filename, s->fpr, s->status);
437 if (s->status || s->wrong_key_usage
438 || !(s->summary & GPGME_SIGSUM_VALID))
439 continue;
441 pp = strv_cat (crypto->sigkey, str_dup (s->fpr));
442 if (!pp)
444 rc = GPG_ERR_ENOMEM;
445 break;
448 crypto->sigkey = pp;
451 xfree (crypto->plaintext);
452 crypto->plaintext = NULL;
453 crypto->plaintext_size = 0;
455 if (!rc)
456 rc = crypto_data_to_buf (plain, &crypto->plaintext,
457 &crypto->plaintext_size);
461 gpgme_data_release (plain);
462 return rc;
465 void
466 crypto_free_key_list (gpgme_key_t *keys)
468 int i;
470 for (i = 0; keys && keys[i]; i++)
471 gpgme_key_unref (keys[i]);
473 xfree (keys);
476 gpgme_error_t
477 crypto_encrypt (struct client_s *client, struct crypto_s *crypto)
479 gpgme_error_t rc;
480 gpgme_data_t cipher;
481 gpgme_key_t *keys = NULL;
482 gpgme_key_t *sigkeys = NULL;
484 STATUS_TIMEOUT_INIT (crypto);
485 rc = crypto_list_keys (crypto, crypto->save.pubkey, 0, &keys);
486 if (rc)
487 return rc;
489 rc = gpgme_data_new (&cipher);
490 if (!rc)
491 rc = gpgme_data_set_file_name (cipher, crypto->filename);
493 if (!rc)
495 rc = crypto_list_keys (crypto, crypto->save.sigkey, 1, &sigkeys);
496 if (gpg_err_code (rc) == GPG_ERR_NO_DATA)
497 rc = 0;
500 if (!rc)
502 gpgme_data_t plain;
504 rc = gpgme_data_new_from_mem (&plain, (char *)crypto->plaintext,
505 crypto->plaintext_size, 0);
506 if (!rc)
508 int i;
510 gpgme_signers_clear (crypto->ctx);
512 for (i = 0; sigkeys && sigkeys[i]; i++)
513 gpgme_signers_add (crypto->ctx, sigkeys[i]);
515 if (!i)
516 rc = GPG_ERR_NO_SIGNATURE_SCHEME;
519 if (!rc)
521 gpgme_data_set_encoding (cipher, GPGME_DATA_ENCODING_ARMOR);
523 rc = send_status (client ? client->ctx : NULL, STATUS_ENCRYPT, NULL);
524 if (!rc)
526 unsigned flags = 0;
527 int f = config_get_boolean ("global", "encrypt_to");
529 if (!f)
530 flags |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
532 f = config_get_boolean ("global", "always_trust");
533 if (f)
534 flags |= GPGME_ENCRYPT_ALWAYS_TRUST;
536 rc = gpgme_op_encrypt_sign_start (crypto->ctx, keys, flags,
537 plain, cipher);
541 if (!rc)
545 if (!rc && crypto->progress_rc)
546 rc = crypto->progress_rc;
548 if (!rc)
549 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_ENCRYPT, NULL);
551 if (rc)
552 break;
553 } while (!gpgme_wait (crypto->ctx, &rc, 0) && !rc);
555 if (!rc)
557 gpgme_encrypt_result_t result;
558 gpgme_sign_result_t sresult;
559 gpgme_invalid_key_t inv;
561 result = gpgme_op_encrypt_result (crypto->ctx);
562 inv = result->invalid_recipients;
563 while (inv)
565 log_write (_ ("%s: invalid recipient: %s, rc=%u"),
566 crypto->filename, inv->fpr, inv->reason);
567 inv = inv->next;
570 sresult = gpgme_op_sign_result (crypto->ctx);
571 inv = sresult->invalid_signers;
572 while (inv)
574 log_write (_ ("%s: invalid signer: %s, rc=%u"),
575 crypto->filename, inv->fpr, inv->reason);
576 inv = inv->next;
579 crypto->cipher = cipher;
583 gpgme_data_release (plain);
586 crypto_free_key_list (keys);
587 crypto_free_key_list (sigkeys);
589 if (rc)
590 gpgme_data_release (cipher);
592 return rc;
595 gpgme_error_t
596 crypto_passwd (struct client_s *client, struct crypto_s *crypto)
598 gpgme_error_t rc;
599 gpgme_key_t *keys = NULL;
601 rc = crypto_list_keys (crypto, crypto->pubkey, 1, &keys);
602 if (rc)
603 return rc;
605 STATUS_TIMEOUT_INIT (crypto);
606 rc = send_status (client->ctx, STATUS_PASSWD, NULL);
607 rc = gpgme_op_passwd_start (crypto->ctx, keys[0], 0);
608 if (!rc)
612 if (!rc && crypto->progress_rc)
613 rc = crypto->progress_rc;
615 if (!rc)
616 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_PASSWD, NULL);
618 if (rc)
619 break;
620 } while (!gpgme_wait (crypto->ctx, &rc, 0) && !rc);
623 crypto_free_key_list (keys);
624 return rc;
627 /* Generate a new key pair. The resulting keyid's are stored in crypto->save.
629 gpgme_error_t
630 crypto_genkey (struct client_s *client, struct crypto_s *crypto,
631 const unsigned char *params)
633 gpgme_genkey_result_t result;
634 gpgme_error_t rc;
636 STATUS_TIMEOUT_INIT (crypto);
637 rc = send_status (client ? client->ctx : NULL, STATUS_GENKEY, NULL);
638 if (!rc)
639 rc = gpgme_op_genkey_start (crypto->ctx, (const char *)params, NULL, NULL);
641 if (rc)
642 return rc;
646 if (!rc && crypto->progress_rc)
647 rc = crypto->progress_rc;
649 if (!rc)
650 STATUS_TIMEOUT_TEST (crypto, rc, STATUS_GENKEY, NULL);
652 if (rc)
653 break;
654 } while (!gpgme_wait (crypto->ctx, &rc, 0) && !rc);
656 if (!rc)
658 result = gpgme_op_genkey_result (crypto->ctx);
659 crypto->save.pubkey = strv_cat (crypto->save.pubkey,
660 str_dup (result->fpr));
661 crypto->save.sigkey = strv_cat (crypto->save.sigkey,
662 str_dup (result->fpr));
663 rc = send_status (client ? client->ctx : NULL, STATUS_GENKEY, "%s",
664 result->fpr);
667 return rc;
670 char *
671 crypto_default_key_params ()
673 char *user = get_username (getuid());
674 char *params = str_asprintf(
675 "<GnupgKeyParms format=\"internal\">\n"
676 " Key-Type: default\n"
677 " Subkey-Type: default\n"
678 " Name-Real: %s\n"
679 " Name-Email: %s\n"
680 " Expire-Date: 0\n"
681 "</GnupgKeyParms>",
682 getenv ("REALNAME") ? getenv ("REALNAME") : user,
683 getenv ("EMAIL") ? getenv ("EMAIL") : user);
685 xfree (user);
686 return params;
689 gpg_error_t
690 crypto_write_file (struct crypto_s *crypto)
692 unsigned char *buf;
693 size_t size, len;
694 int fd;
695 gpg_error_t rc;
696 char tmp[PATH_MAX];
697 struct stat st;
698 mode_t mode = 0600;
700 if (crypto->filename)
702 if (lstat (crypto->filename, &st) == 0)
704 mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
706 if (!(mode & S_IWUSR))
707 return GPG_ERR_EACCES;
709 else if (errno != ENOENT)
710 return gpg_error_from_errno (errno);
712 snprintf (tmp, sizeof (tmp), "%s.XXXXXX", crypto->filename);
713 fd = mkstemp (tmp);
714 if (fd == -1)
716 rc = gpg_error_from_errno (errno);
717 log_write ("%s: %s", tmp, pwmd_strerror (rc));
718 return rc;
721 else
722 fd = STDOUT_FILENO;
724 rc = crypto_data_to_buf (crypto->cipher, &buf, &size);
725 len = write (fd, buf, size);
726 xfree (buf);
727 if (len != size)
728 rc = gpg_error_from_errno (errno);
730 if (!rc)
732 if (fsync (fd) != -1)
734 if (crypto->filename && close (fd) != -1)
736 fd = -1;
737 if (mode && config_get_boolean (crypto->filename, "backup"))
739 char tmp2[PATH_MAX];
741 snprintf (tmp2, sizeof (tmp2), "%s.backup", crypto->filename);
742 if (rename (crypto->filename, tmp2) == -1)
743 if (errno != ENOENT)
744 rc = gpg_error_from_errno (errno);
747 else if (crypto->filename)
748 rc = gpg_error_from_errno (errno);
750 else
751 rc = gpg_error_from_errno (errno);
754 if (!rc)
756 if (crypto->filename && rename (tmp, crypto->filename) == -1)
757 rc = gpg_error_from_errno (errno);
758 else if (crypto->filename && mode)
759 chmod (crypto->filename, mode);
762 if (fd != -1)
763 close (fd);
765 return rc;
768 char *
769 crypto_key_info (const gpgme_key_t key)
771 struct string_s *string = string_new (NULL), *s;
772 char *line = NULL;
773 unsigned n, u;
774 gpgme_subkey_t subkey;
775 gpgme_user_id_t uid;
777 if (!string)
778 return NULL;
780 for (u = 0, uid = key->uids; uid; uid = uid->next)
781 u++;
783 for (n = 0, subkey = key->subkeys; subkey; subkey = subkey->next)
784 n++;
786 s = string_append_printf (string, "%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%i:%i:%u:%u",
787 key->revoked, key->expired, key->disabled,
788 key->invalid, key->can_encrypt, key->can_sign,
789 key->can_certify, key->secret,
790 key->can_authenticate, key->is_qualified,
791 key->protocol, key->owner_trust, u, n);
792 if (!s)
794 string_free (string, 1);
795 return NULL;
798 string = s;
799 for (subkey = key->subkeys; subkey; subkey = subkey->next)
801 char *tmp;
803 s = string_append_printf (string, ":%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%u:%i:%u",
804 subkey->revoked, subkey->expired,
805 subkey->disabled, subkey->invalid,
806 subkey->can_encrypt, subkey->can_sign,
807 subkey->can_certify, subkey->secret,
808 subkey->can_authenticate, subkey->is_qualified,
809 subkey->is_cardkey, subkey->pubkey_algo,
810 subkey->length);
811 if (!s)
813 string_free (string, 1);
814 return NULL;
817 string = s;
818 s = string_append_printf (string, ":%s:%s:%li:%li:%s",
819 subkey->keyid, subkey->fpr, subkey->timestamp,
820 subkey->expires,
821 subkey->card_number ? subkey->card_number : "0");
822 if (!s)
824 string_free (string, 1);
825 return NULL;
828 string = s;
829 tmp = openpgp_escape (subkey->curve);
830 s = string_append_printf (string, ":%s", tmp ? tmp : "");
831 xfree (tmp);
832 if (!s)
834 string_free (string, 1);
835 return NULL;
838 string = s;
841 for (uid = key->uids; uid; uid = uid->next)
843 char *userid, *name, *email, *comment;
845 userid = openpgp_escape (uid->uid);
846 name = openpgp_escape (uid->name);
847 email = openpgp_escape (uid->email);
848 comment = openpgp_escape (uid->comment);
849 s = string_append_printf (string, ":%u:%u:%u:%s:%s:%s:%s",
850 uid->revoked, uid->invalid, uid->validity,
851 userid ? userid : "",
852 name ? name : "",
853 email ? email : "",
854 comment ? comment : "");
855 xfree (userid);
856 xfree (name);
857 xfree (email);
858 xfree (comment);
859 if (!s)
861 string_free (string, 1);
862 return NULL;
865 string = s;
868 line = string->str;
869 string_free (string, 0);
870 return line;
873 gpg_error_t
874 crypto_try_decrypt (struct client_s *client, int no_pinentry)
876 struct crypto_s *crypto;
877 gpg_error_t rc;
879 rc = crypto_init (&crypto, client->ctx, client->filename, no_pinentry);
880 if (!rc)
882 rc = crypto_decrypt (client, crypto);
883 crypto_cleanup (crypto);
886 return rc;