Consider INQUIRE_MAXLEN when exporting and cache pushing.
[pwmd.git] / src / agent.c
blob2c3694418c5a136d074989b5b26f936e19a1311f
1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
2 /*
3 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
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 <stdlib.h>
26 #include <glib.h>
27 #include <glib/gprintf.h>
28 #include <glib/gstdio.h>
29 #include <errno.h>
30 #include <pwd.h>
31 #include <signal.h>
32 #include <sys/types.h>
33 #include <sys/wait.h>
34 #include <fcntl.h>
35 #include <dirent.h>
36 #include "pwmd-error.h"
37 #include "mem.h"
38 #include "common.h"
39 #include "commands.h"
40 #include "agent.h"
41 #include "misc.h"
42 #include "mutex.h"
43 #include "rcfile.h"
44 #include "cache.h"
45 #include "cipher.h"
47 #ifdef WITH_LIBACL
48 #include <acl/libacl.h>
49 #endif
51 #ifdef __FreeBSD__
52 #include <sys/types.h>
53 #include <signal.h>
54 #endif
56 static guint8 pwmd_magic[5] = { '\177', 'P', 'W', 'M', 'D' };
58 static gpg_error_t mem_realloc_cb(void *data, const void *buffer, size_t len)
60 membuf_t *mem = (membuf_t *)data;
61 void *p;
63 if (!buffer)
64 return 0;
66 if ((p = xrealloc(mem->buf, mem->len + len)) == NULL)
67 return 1;
69 mem->buf = p;
70 memcpy((char *)mem->buf + mem->len, buffer, len);
71 mem->len += len;
72 return 0;
75 static gpg_error_t status_cb(gpointer data, const gchar *line)
77 struct agent_s *agent = data;
79 agent->inquire_maxlen = 0;
81 if (!strncmp(line, "INQUIRE_MAXLEN ", 15))
82 agent->inquire_maxlen = atoi(line+15);
84 return send_status(agent->client_ctx, STATUS_AGENT, "%s", line);
87 static gpg_error_t assuan_command(struct agent_s *a, gchar **result,
88 gsize *len, const gchar *cmd)
90 gpg_error_t rc;
92 a->data.len = 0;
93 a->data.buf = NULL;
94 if (result)
95 *result = NULL;
96 if (len)
97 *len = 0;
98 rc = assuan_transact(a->ctx, cmd, mem_realloc_cb, &a->data,
99 a->inquire_cb, a->inquire_data, status_cb, a);
101 if (rc)
102 xfree(a->data.buf);
103 else {
104 if (a->data.buf) {
105 mem_realloc_cb(&a->data, "", 1);
106 if (result)
107 *result = (gchar *)a->data.buf;
108 else
109 xfree(a->data.buf);
111 if (len)
112 *len = a->data.len;
116 return rc;
119 /* This commands are sent from launch_agent() after reconnecting to the agent
120 * and also from the initial client connection. */
121 static gpg_error_t send_agent_common_options(struct agent_s *agent)
123 gpg_error_t rc;
125 rc = send_to_agent(agent, NULL, NULL, "OPTION cache-ttl-opt-preset=-1");
126 return rc;
129 static gpg_error_t launch_agent(struct agent_s *agent)
131 gpg_error_t rc;
132 assuan_context_t ctx;
133 const gchar *t = NULL;
134 static struct assuan_malloc_hooks mhooks = { xmalloc, xrealloc, xfree };
135 gchar *s, buf[LINE_MAX];
136 FILE *fp;
138 s = get_key_file_string("global", "agent_env_file");
139 if (s) {
140 gchar *ss = expand_homedir(s);
142 g_free(s);
143 fp = fopen(ss, "r");
144 g_free(ss);
146 if (fp) {
147 while ((s = fgets(buf, sizeof(buf), fp))) {
148 s = g_strchomp(s);
149 if (g_str_has_prefix(s, "GPG_AGENT_INFO=")) {
150 g_setenv("GPG_AGENT_INFO", s+strlen("GPG_AGENT_INFO="), TRUE);
151 break;
155 fclose(fp);
157 else
158 log_write("%s: %s", s, pwmd_strerror(gpg_error_from_syserror()));
161 t = g_getenv("GPG_AGENT_INFO");
162 if (!t)
163 return gpg_err_code(GPG_ERR_NO_AGENT);
165 rc = assuan_new_ext(&ctx, GPG_ERR_SOURCE_DEFAULT, &mhooks,
166 debug_level ? assuan_log_cb : NULL, "AGENT ");
167 if (rc)
168 return rc;
170 gchar **fields = g_strsplit(t, ":", 0);
171 rc = assuan_socket_connect(ctx, fields[0], ASSUAN_INVALID_PID, 0);
172 g_strfreev(fields);
173 if (rc) {
174 assuan_release(ctx);
175 return rc;
178 if (agent->ctx) {
179 /* Restore the previous agent settings for this new context. */
180 assuan_release(agent->ctx);
181 agent->ctx = ctx;
182 rc = send_agent_common_options(agent);
183 if (!rc && agent->display)
184 rc = set_agent_option(agent, "display", agent->display);
186 if (!rc && agent->ttyname)
187 rc = set_agent_option(agent, "ttyname", agent->ttyname);
189 if (!rc && agent->ttytype)
190 rc = set_agent_option(agent, "ttytype", agent->ttytype);
192 if (!rc && agent->lc_messages)
193 rc = set_agent_option(agent, "lc-messages", agent->lc_messages);
195 if (!rc && agent->lc_ctype)
196 rc = set_agent_option(agent, "lc-ctype", agent->lc_ctype);
199 agent->ctx = ctx;
200 return 0;
203 gpg_error_t send_to_agent(struct agent_s *agent, gchar **result, gsize *len,
204 const gchar *fmt, ...)
206 gpg_error_t rc = 0;
207 va_list ap;
208 gchar *cmd;
210 if (!agent->ctx) {
211 rc = launch_agent(agent);
212 if (rc)
213 return rc;
216 va_start(ap, fmt);
217 if (g_vasprintf(&cmd, fmt, ap) > 0) {
218 rc = assuan_command(agent, result, len, cmd);
219 if (!agent->restart && gpg_err_source(rc) == GPG_ERR_SOURCE_DEFAULT
220 && (gpg_err_code(rc) == GPG_ERR_ASS_CONNECT_FAILED
221 || gpg_err_code(rc) == GPG_ERR_EPIPE)) {
222 g_unsetenv("GPG_AGENT_INFO");
223 agent->restart = TRUE;
224 rc = launch_agent(agent);
225 if (!rc)
226 rc = assuan_command(agent, result, len, cmd);
229 agent->restart = FALSE;
230 g_free(cmd);
232 else
233 rc = GPG_ERR_ENOMEM;
235 va_end(ap);
236 return rc;
239 static void agent_disconnect(struct agent_s *agent)
241 if (!agent)
242 return;
244 if (agent->ctx)
245 assuan_release(agent->ctx);
247 agent->ctx = NULL;
250 void cleanup_agent(struct agent_s *agent)
252 if (!agent)
253 return;
255 g_free(agent->desc);
256 g_free(agent->display);
257 g_free(agent->ttyname);
258 g_free(agent->ttytype);
259 g_free(agent->lc_messages);
260 g_free(agent->lc_ctype);
262 if (agent->ctx)
263 agent_disconnect(agent);
265 g_free(agent);
268 gpg_error_t agent_init(struct agent_s **agent)
270 struct agent_s *new = g_malloc0(sizeof(struct agent_s));
272 if (!new)
273 return GPG_ERR_ENOMEM;
275 *agent = new;
276 return 0;
279 void set_header_defaults(file_header_t *hdr)
281 gchar *s = get_key_file_string(NULL, "cipher");
282 gint flags = cipher_string_to_cipher(s);
284 g_free(s);
285 memset(hdr, 0, sizeof(file_header_t));
286 memcpy(hdr->magic, pwmd_magic, sizeof(hdr->magic));
287 if (flags == -1)
288 log_write(_("Invalid 'cipher' in configuration file. Using a default of aes256."));
289 hdr->flags = flags == -1 ? PWMD_CIPHER_AES256 : flags;
290 hdr->version = VERSION_HEX;
293 gpg_error_t read_data_header(const gchar *filename, file_header_t *rhdr,
294 struct stat *rst, gint *rfd)
296 gpg_error_t rc = 0;
297 gsize len;
298 struct stat st;
299 file_header_t hdr;
300 gint fd;
302 if (g_lstat(filename, &st) == -1)
303 return gpg_error_from_syserror();
305 if (!S_ISREG(st.st_mode))
306 return GPG_ERR_ENOANO;
308 fd = open(filename, O_RDONLY);
309 if (fd == -1)
310 return gpg_error_from_syserror();
312 len = read(fd, &hdr, sizeof(file_header_t));
313 if (len != sizeof(file_header_t))
314 rc = rc == -1 ? gpg_error_from_syserror() : GPG_ERR_BAD_DATA;
316 if (!rc && memcmp(hdr.magic, pwmd_magic, sizeof(hdr.magic)))
317 rc = GPG_ERR_BAD_DATA;
318 else if (hdr.version < 0x0300)
319 rc = GPG_ERR_UNKNOWN_VERSION;
321 if (rc)
322 close(fd);
323 else {
324 if (rhdr)
325 *rhdr = hdr;
326 if (rst)
327 *rst = st;
328 if (rfd)
329 *rfd = fd;
330 else
331 close(fd);
334 return rc;
337 gpg_error_t read_data_file(const gchar *filename, struct crypto_s *crypto)
339 gint fd;
340 gpg_error_t rc = 0;
341 gsize len, rlen;
342 gchar *buf = NULL;
344 cleanup_crypto_stage1(crypto);
345 rc = read_data_header(filename, &crypto->hdr, &crypto->st, &fd);
346 if (rc)
347 return rc;
349 crypto->ciphertext_len = crypto->hdr.datalen;
350 crypto->ciphertext = g_malloc(crypto->hdr.datalen);
351 if (!crypto->ciphertext) {
352 rc = GPG_ERR_ENOMEM;
353 goto fail;
356 len = read(fd, crypto->ciphertext, crypto->hdr.datalen);
357 if (len != crypto->hdr.datalen) {
358 rc = rc == -1 ? gpg_error_from_syserror() : GPG_ERR_BAD_DATA;
359 goto fail;
362 rlen = read(fd, crypto->grip, 20);
363 if (rlen != 20) {
364 rc = rc == -1 ? gpg_error_from_syserror() : GPG_ERR_BAD_DATA;
365 goto fail;
368 rlen = read(fd, crypto->sign_grip, 20);
369 if (rlen != 20) {
370 rc = rc == -1 ? gpg_error_from_syserror() : GPG_ERR_BAD_DATA;
371 goto fail;
374 len = crypto->st.st_size-sizeof(file_header_t)-crypto->hdr.datalen-40;
375 buf = g_malloc(len);
376 if (!buf) {
377 rc = GPG_ERR_ENOMEM;
378 goto fail;
381 rlen = read(fd, buf, len);
382 if (rlen != len) {
383 rc = rc == -1 ? gpg_error_from_syserror() : GPG_ERR_BAD_DATA;
384 goto fail;
387 rc = gcry_sexp_new(&crypto->ciphertext_sexp, buf, rlen, 1);
388 if (rc)
389 goto fail;
391 if (crypto->pkey_sexp)
392 gcry_sexp_release(crypto->pkey_sexp);
394 if (crypto->sigpkey_sexp)
395 gcry_sexp_release(crypto->sigpkey_sexp);
397 crypto->pkey_sexp = crypto->sigpkey_sexp = NULL;
398 rc = get_pubkey_bin(crypto, crypto->grip, &crypto->pkey_sexp);
399 if (!rc)
400 rc = get_pubkey_bin(crypto, crypto->sign_grip, &crypto->sigpkey_sexp);
402 fail:
403 close(fd);
404 g_free(buf);
405 return rc;
408 static gpg_error_t inquire_cb(gpointer user, const char *keyword)
410 struct inquire_data_s *idata = user;
412 if (!idata->preset && (!g_strcmp0(keyword, "PASSPHRASE")
413 || !g_strcmp0(keyword, "NEW_PASSPHRASE"))) {
414 return agent_loopback_cb(idata->crypto, keyword);
416 // SAVE --inquire-keyparam
417 else if (idata->preset && !g_strcmp0(keyword, "KEYPARAM")) {
418 idata->preset = FALSE;
419 return agent_loopback_cb(idata->crypto, keyword);
422 if (idata->crypto->agent->inquire_maxlen
423 && idata->len > idata->crypto->agent->inquire_maxlen) {
424 log_write(_("Inquired data too large: have=%u, max=%u"), idata->len,
425 idata->crypto->agent->inquire_maxlen);
426 return GPG_ERR_TOO_LARGE;
429 idata->crypto->agent->inquire_maxlen = 0;
430 return assuan_send_data(idata->crypto->agent->ctx, idata->line, idata->len);
433 static gpg_error_t extract_key(struct crypto_s *crypto, guchar **result,
434 gsize *result_len)
436 gpg_error_t rc;
437 gcry_sexp_t enc_sexp = NULL, tmp_sexp;
438 struct inquire_data_s idata = {0};
439 gchar *hexgrip = NULL;
440 gchar *key;
441 gsize keylen, keysize;
442 gchar *tmp;
443 gint algo = cipher_to_gcrypt(crypto->hdr.flags);
444 gboolean shadowed;
446 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_KEYLEN, NULL, &keysize);
447 if (rc)
448 return rc;
450 tmp_sexp = gcry_sexp_find_token(crypto->ciphertext_sexp, "enc-val", 0);
451 if (!tmp_sexp)
452 return GPG_ERR_BAD_DATA;
454 hexgrip = bin2hex(crypto->grip, sizeof(crypto->grip));
455 if (!hexgrip) {
456 rc = GPG_ERR_ENOMEM;
457 goto fail;
460 rc = cache_is_shadowed(hexgrip);
461 if (rc && rc != GPG_ERR_NO_DATA)
462 goto fail;
464 shadowed = !rc ? TRUE : FALSE;
465 if (!shadowed) {
466 gcry_sexp_t tmp2_sexp = gcry_sexp_cdr(tmp_sexp);
467 gcry_sexp_release(tmp_sexp);
468 tmp_sexp = gcry_sexp_nth(tmp2_sexp, 0);
469 gcry_sexp_release(tmp2_sexp);
470 rc = gcry_sexp_build(&enc_sexp, NULL, "(enc-val (flags pkcs1) %S)",
471 tmp_sexp);
473 else
474 rc = gcry_sexp_build(&enc_sexp, NULL, "%S", tmp_sexp);
476 gcry_sexp_release(tmp_sexp);
477 if (rc)
478 return rc;
480 crypto->agent->inquire_cb = inquire_cb;
481 idata.crypto = crypto;
482 idata.len = gcry_sexp_sprint(enc_sexp, GCRYSEXP_FMT_CANON, NULL, 0);
483 idata.line = g_malloc(idata.len);
484 if (!idata.line) {
485 rc = GPG_ERR_ENOMEM;
486 goto fail;
489 idata.len = gcry_sexp_sprint(enc_sexp, GCRYSEXP_FMT_CANON, idata.line,
490 idata.len);
491 crypto->agent->inquire_data = &idata;
492 gcry_sexp_release(enc_sexp);
493 enc_sexp = NULL;
494 log_write1(_("Keygrip is %s, bits=%i"), hexgrip,
495 gcry_pk_get_nbits(crypto->pkey_sexp));
496 rc = send_to_agent(crypto->agent, NULL, NULL, "SETKEY %s", hexgrip);
497 if (rc)
498 goto fail;
500 if (!crypto->agent->desc) {
501 tmp = plus_escape(_(
502 "A %s is required to unlock the secret key for the "
503 "encrypted data file \"%s\". Please enter the %s "
504 "below."),
505 shadowed ? "PIN" : _("passphrase"), crypto->filename,
506 shadowed ? "PIN" : _("passphrase"));
508 else
509 tmp = plus_escape(crypto->agent->desc);
511 rc = send_to_agent(crypto->agent, NULL, NULL, "SETKEYDESC %s", tmp);
512 g_free(tmp);
513 if (rc)
514 goto fail;
516 assuan_begin_confidential(crypto->agent->ctx);
517 rc = send_to_agent(crypto->agent, &key, &keylen, "PKDECRYPT");
518 assuan_end_confidential(crypto->agent->ctx);
519 if (rc)
520 goto fail;
522 rc = gcry_sexp_new(&tmp_sexp, key, keylen, 1);
523 xfree(key);
524 if (rc)
525 goto fail;
527 key = (gchar *)gcry_sexp_nth_data(tmp_sexp, 1, result_len);
528 if (key) {
529 *result = gcry_malloc(*result_len);
530 if (!*result)
531 rc = GPG_ERR_ENOMEM;
532 else
533 memcpy(*result, key, *result_len);
535 else
536 rc = GPG_ERR_BAD_DATA;
538 gcry_sexp_release(tmp_sexp);
540 fail:
541 g_free(idata.line);
542 g_free(hexgrip);
544 if (enc_sexp)
545 gcry_sexp_release(enc_sexp);
547 return rc;
550 static gpg_error_t verify(gcry_sexp_t pkey, gcry_sexp_t sig_sexp,
551 const gpointer data, gsize len)
553 gpg_error_t rc;
554 guint hashlen = gcry_md_get_algo_dlen(GCRY_MD_SHA256);
555 guchar *hash;
556 gcry_sexp_t data_sexp;
558 hash = gcry_malloc(hashlen);
559 if (!hash)
560 return GPG_ERR_ENOMEM;
562 gcry_md_hash_buffer(GCRY_MD_SHA256, hash, data, len);
563 rc = gcry_sexp_build(&data_sexp, NULL,
564 "(data (flags pkcs1) (hash sha256 %b))", hashlen, hash);
565 gcry_free(hash);
566 if (!rc) {
567 rc = gcry_pk_verify(sig_sexp, data_sexp, pkey);
568 gcry_sexp_release(data_sexp);
571 return rc;
574 gpg_error_t decrypt_data(struct crypto_s *crypto)
576 gpg_error_t rc;
577 guchar *key = NULL;
578 gsize keylen = 0;
579 gcry_cipher_hd_t h = NULL;
580 gsize blocksize, keysize;
581 gint algo = cipher_to_gcrypt(crypto->hdr.flags);
582 gpointer outbuf = NULL;
583 gcry_sexp_t sig_sexp;
585 rc = extract_key(crypto, &key, &keylen);
586 if (rc)
587 return rc;
589 sig_sexp = gcry_sexp_find_token(crypto->ciphertext_sexp, "sig-val", 0);
590 if (!sig_sexp) {
591 rc = GPG_ERR_BAD_DATA;
592 goto fail;
595 rc = verify(crypto->sigpkey_sexp, sig_sexp, crypto->ciphertext, crypto->ciphertext_len);
596 gcry_sexp_release(sig_sexp);
597 if (rc)
598 goto fail;
600 rc = gcry_cipher_open(&h, algo, GCRY_CIPHER_MODE_CBC, 0);
601 if (rc)
602 goto fail;
604 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_KEYLEN, NULL, &keysize);
605 if (rc)
606 goto fail;
607 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_BLKLEN, NULL, &blocksize);
608 if (rc)
609 goto fail;
611 rc = gcry_cipher_setiv(h, crypto->hdr.iv, sizeof(crypto->hdr.iv));
612 if (rc)
613 goto fail;
615 rc = gcry_cipher_setkey(h, key, keylen);
616 if (rc)
617 goto fail;
619 outbuf = gcry_malloc(crypto->hdr.datalen);
620 if (!outbuf) {
621 rc = GPG_ERR_ENOMEM;
622 goto fail;
625 rc = gcry_cipher_decrypt(h, outbuf, crypto->hdr.datalen,
626 crypto->ciphertext, crypto->hdr.datalen);
627 if (rc)
628 gcry_free(outbuf);
629 else {
630 crypto->plaintext = outbuf;
631 crypto->plaintext_len = crypto->hdr.datalen;
634 fail:
635 gcry_free(key);
636 gcry_cipher_close(h);
637 return rc;
640 static gpg_error_t encrypt_xml(gpointer key, gsize keylen, gint algo,
641 const gpointer xml, gsize len, gpointer *result, gsize *result_len,
642 guchar **iv, gsize *iv_len)
644 gpg_error_t rc;
645 gcry_cipher_hd_t h;
646 gsize blocksize, keysize;
647 gpointer inbuf = NULL;
648 gsize olen = len;
650 rc = gcry_cipher_open(&h, algo, GCRY_CIPHER_MODE_CBC, 0);
651 if (rc)
652 return rc;
654 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_KEYLEN, NULL, &keysize);
655 if (rc)
656 goto fail;
658 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_BLKLEN, NULL, &blocksize);
659 if (rc)
660 goto fail;
662 *(iv) = g_malloc(blocksize);
663 if (!*(iv))
664 goto fail;
666 *iv_len = blocksize;
667 gcry_create_nonce(*(iv), blocksize);
668 rc = gcry_cipher_setiv(h, *(iv), blocksize);
669 if (rc)
670 goto fail;
672 rc = gcry_cipher_setkey(h, key, keylen);
673 if (rc)
674 goto fail;
676 if (len%blocksize)
677 len += blocksize-(len%blocksize);
679 inbuf = gcry_malloc(len);
680 if (!inbuf) {
681 rc = GPG_ERR_ENOMEM;
682 goto fail;
685 memset(inbuf, 0, len);
686 memcpy(inbuf, xml, olen);
687 rc = gcry_cipher_encrypt(h, inbuf, len, NULL, 0);
688 if (rc)
689 goto fail;
691 *result = inbuf;
692 *result_len = len;
693 gcry_cipher_close(h);
694 return 0;
696 fail:
697 if (*(iv))
698 g_free(iv);
700 if (inbuf)
701 gcry_free(inbuf);
703 gcry_cipher_close(h);
704 return rc;
707 gpg_error_t agent_loopback_cb(gpointer user, const gchar *keyword)
709 struct crypto_s *crypto = user;
710 gpg_error_t rc;
711 guchar *result;
712 gsize len;
713 gboolean keyparam = FALSE;
715 if (!g_strcmp0(keyword, "KEYPARAM")) {
716 keyparam = TRUE;
717 rc = assuan_inquire(crypto->client_ctx, keyword, &result, &len, 0);
719 else { // PASSPHRASE or NEW_PASSPHRASE
720 assuan_begin_confidential(crypto->client_ctx);
721 rc = assuan_inquire(crypto->client_ctx, keyword, &result, &len, 0);
722 assuan_end_confidential(crypto->client_ctx);
725 if (!rc) {
726 if (keyparam && !len) {
727 gchar *tmp = default_key_params(crypto);
729 if (!tmp)
730 return gpg_error(GPG_ERR_ENOMEM);
732 len = strlen(tmp);
733 result = xmalloc(len);
734 memcpy(result, tmp, len);
735 g_free(tmp);
738 pthread_cleanup_push(xfree, result);
740 if (keyparam)
741 rc = assuan_send_data(crypto->agent->ctx, result, len);
742 else {
743 assuan_begin_confidential(crypto->agent->ctx);
744 rc = assuan_send_data(crypto->agent->ctx, result, len);
745 assuan_end_confidential(crypto->agent->ctx);
748 pthread_cleanup_pop(1);
750 else if (gpg_err_code(rc) == GPG_ERR_ASS_CANCELED) {
751 gpg_error_t arc = assuan_write_line(crypto->agent->ctx, "CAN");
753 if (!arc) {
754 char *line;
755 size_t len;
757 arc = assuan_read_line(crypto->agent->ctx, &line, &len);
758 if (arc)
759 rc = arc;
761 else
762 rc = arc;
765 return rc;
768 static gpg_error_t sign(gcry_sexp_t *rsexp, const gchar *sign_hexgrip,
769 struct crypto_s *crypto, const gpointer data, gsize len)
771 gpg_error_t rc;
772 gchar *result;
773 gchar *tmp = sign_hexgrip ? g_strdup(sign_hexgrip)
774 : bin2hex(crypto->grip, sizeof(crypto->grip));
776 pthread_cleanup_push(g_free, tmp);
777 log_write1(_("Sign keygrip is %s"), tmp);
778 rc = send_to_agent(crypto->agent, NULL, NULL, "SIGKEY %s", tmp);
779 pthread_cleanup_pop(1);
780 if (!rc) {
781 guchar *hash;
782 guint hashlen = gcry_md_get_algo_dlen(GCRY_MD_SHA256);
784 hash = gcry_malloc(hashlen);
785 if (!hash)
786 return GPG_ERR_ENOMEM;
788 gcry_md_hash_buffer(GCRY_MD_SHA256, hash, data, len);
789 tmp = bin2hex(hash, hashlen);
790 gcry_free(hash);
791 pthread_cleanup_push(g_free, tmp);
792 rc = send_to_agent(crypto->agent, NULL, NULL,
793 "SETHASH --hash=sha256 %s", tmp);
794 pthread_cleanup_pop(1);
797 if (!rc) {
798 struct inquire_data_s idata = {0};
800 idata.crypto = crypto;
801 crypto->agent->inquire_data = &idata;
802 crypto->agent->inquire_cb = inquire_cb;
803 rc = send_to_agent(crypto->agent, &result, &len, "PKSIGN");
804 if (!rc) {
805 rc = gcry_sexp_sscan(rsexp, NULL, result, len);
806 xfree(result);
810 return rc;
813 static gpg_error_t write_file(struct crypto_s *crypto, const gchar *filename,
814 gpointer data, gsize data_len, gpointer sexp, gsize sexp_len)
816 gchar tmp[FILENAME_MAX] = { 0 };
817 mode_t mode = 0;
818 struct stat st;
819 gint fd;
820 gpg_error_t rc = 0;
821 gsize len;
822 #ifdef WITH_LIBACL
823 acl_t acl = NULL;
824 #endif
826 if (filename) {
827 if (g_lstat(filename, &st) == 0) {
828 mode = st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO);
830 if (!(mode & S_IWUSR))
831 return GPG_ERR_EACCES;
833 else if (errno != ENOENT)
834 return gpg_error_from_syserror();
836 g_snprintf(tmp, sizeof(tmp), "%s.XXXXXX", filename);
837 #if GLIB_CHECK_VERSION(2, 22, 0)
838 fd = g_mkstemp_full(tmp, O_WRONLY, 0600);
839 #else
840 fd = mkstemp(tmp);
841 #endif
842 if (fd == -1) {
843 rc = gpg_error_from_syserror();
844 log_write("%s: %s", tmp, pwmd_strerror(rc));
845 return rc;
848 else {
849 // xml_import() or convert_file() from command line.
850 fd = STDOUT_FILENO;
853 pthread_cleanup_push(cleanup_unlink_cb, tmp);
854 crypto->save.hdr.version = VERSION_HEX;
855 len = write(fd, &crypto->save.hdr, sizeof(file_header_t));
856 if (len == sizeof(file_header_t)) {
857 len = write(fd, data, data_len);
858 if (len == data_len) {
859 len = write(fd, sexp, sexp_len);
860 if (len != sexp_len)
861 rc = gpg_error_from_syserror();
863 else
864 rc = gpg_error_from_syserror();
866 else
867 rc = gpg_error_from_syserror();
869 #ifdef WITH_LIBACL
870 pthread_cleanup_push(acl_free, acl);
871 #endif
872 if (!rc) {
873 if (fsync(fd) != -1) {
874 if (filename && close(fd) != -1) {
875 if (mode && get_key_file_boolean(filename, "backup")) {
876 gchar tmp2[FILENAME_MAX];
878 g_snprintf(tmp2, sizeof(tmp2), "%s.backup", filename);
879 #ifdef WITH_LIBACL
880 acl = acl_get_file(filename, ACL_TYPE_ACCESS);
881 if (!acl)
882 log_write("ACL: %s: %s", filename,
883 pwmd_strerror(gpg_error_from_syserror()));
884 #endif
886 if (g_rename(filename, tmp2) == -1)
887 rc = gpg_error_from_syserror();
889 else if (filename) {
890 #ifdef WITH_LIBACL
891 acl = acl_get_file(".", ACL_TYPE_DEFAULT);
892 if (!acl)
893 log_write("ACL: %s: %s", filename,
894 pwmd_strerror(gpg_error_from_syserror()));
895 #endif
898 else if (filename)
899 rc = gpg_error_from_syserror();
901 else
902 rc = gpg_error_from_syserror();
905 if (!rc) {
906 if (filename && g_rename(tmp, filename) != -1) {
907 tmp[0] = 0;
908 if (filename && mode)
909 g_chmod(filename, mode);
911 #ifdef WITH_LIBACL
912 if (filename && acl && acl_set_file(filename, ACL_TYPE_ACCESS, acl))
913 log_write("ACL: %s: %s", filename,
914 pwmd_strerror(gpg_error_from_syserror()));
915 #endif
917 /* Be sure the file entry has been written to disk. On FreeBSD I
918 * noticed delays causing a following command to return
919 * GPG_ERR_CHECKSUM. Recommended from fsync(2) (Linux).
921 DIR *dir;
922 gchar *path;
923 gchar *s = get_key_file_string("global", "data_directory");
925 path = expand_homedir(s);
926 g_free(s);
927 dir = opendir(path);
928 g_free(path);
929 if (dir) {
930 fd = dirfd(dir);
931 if (fd != -1)
932 fsync(fd);
933 else
934 rc = gpg_error_from_syserror();
936 closedir(dir);
938 else
939 rc = gpg_error_from_syserror();
941 else
942 rc = gpg_error_from_syserror();
945 #ifdef WITH_LIBACL
946 pthread_cleanup_pop(1);
947 #endif
948 pthread_cleanup_pop(rc ? 1 : 0); // unlink
949 return rc;
952 gpg_error_t encrypt_data_file(struct crypto_s *crypto, gcry_sexp_t pubkey,
953 gcry_sexp_t sigpkey, const gchar *filename, const gpointer xml,
954 gsize len)
956 gpg_error_t rc;
957 gpointer data = NULL;
958 gsize data_len = 0;
959 gpointer enc_xml = NULL;
960 gsize enc_xml_len = 0;
961 guchar *iv = NULL;
962 gsize iv_len = 0;
963 gint algo = cipher_to_gcrypt(crypto->save.hdr.flags);
964 gpointer key = NULL;
965 gsize keysize;
966 guchar sig_grip[20];
967 guchar grip[20];
969 rc = gcry_cipher_algo_info(algo, GCRYCTL_GET_KEYLEN, NULL, &keysize);
970 if (rc)
971 return rc;
973 pthread_cleanup_push(gcry_free, key);
974 key = gcry_random_bytes_secure(keysize, GCRY_STRONG_RANDOM);
975 pthread_testcancel(); // may have been a long operation
976 pthread_cleanup_pop(0);
977 if (!key)
978 return GPG_ERR_ENOMEM;
980 gcry_pk_get_keygrip(pubkey, grip);
981 gcry_pk_get_keygrip(sigpkey, sig_grip);
982 pthread_cleanup_push(g_free, iv);
983 pthread_cleanup_push(gcry_free, key);
984 rc = encrypt_xml(key, keysize, algo, xml, len, &enc_xml, &enc_xml_len,
985 &iv, &iv_len);
986 if (!rc) {
987 gcry_sexp_t sig_sexp = NULL;
988 gchar *hexgrip = bin2hex(sig_grip, 20);
990 pthread_cleanup_push(gcry_free, enc_xml);
991 rc = sign(&sig_sexp, hexgrip, crypto, enc_xml, enc_xml_len);
992 g_free(hexgrip);
994 if (!rc) {
995 rc = verify(sigpkey, sig_sexp, enc_xml, enc_xml_len);
997 if (!rc) {
998 gcry_sexp_t tmp_sexp;
1000 rc = gcry_sexp_build(&tmp_sexp, NULL,
1001 "(data (flags pkcs1) (value %b))", keysize, key);
1002 if (!rc) {
1003 gcry_sexp_t key_sexp;
1005 pthread_cleanup_push((void (*)(void*))gcry_sexp_release,
1006 (void *)sig_sexp);
1007 rc = gcry_pk_encrypt(&key_sexp, tmp_sexp, pubkey);
1008 pthread_cleanup_pop(0);
1009 gcry_sexp_release(tmp_sexp);
1011 if (!rc) {
1012 memcpy(crypto->save.hdr.iv, iv, iv_len);
1013 crypto->save.hdr.datalen = enc_xml_len;
1014 rc = gcry_sexp_build(&tmp_sexp, NULL, "%S%S", key_sexp,
1015 sig_sexp);
1016 gcry_sexp_release(key_sexp);
1018 if (!rc) {
1019 data_len = gcry_sexp_sprint(tmp_sexp,
1020 GCRYSEXP_FMT_CANON, NULL, 0);
1021 data = g_malloc(data_len+40); // +40 for keygrips
1022 if (data) {
1023 gcry_sexp_sprint(tmp_sexp, GCRYSEXP_FMT_CANON,
1024 data+40, data_len);
1025 data_len += 40;
1027 else
1028 rc = GPG_ERR_ENOMEM;
1030 gcry_sexp_release(tmp_sexp);
1037 pthread_cleanup_pop(0); // enc_xml
1039 if (sig_sexp)
1040 gcry_sexp_release(sig_sexp);
1043 pthread_cleanup_pop(1); // key
1044 pthread_cleanup_pop(1); // iv
1046 if (!rc) {
1047 pthread_cleanup_push(gcry_free, enc_xml);
1048 memcpy(data, grip, 20);
1049 memcpy(data+20, sig_grip, 20);
1050 rc = write_file(crypto, filename, enc_xml, enc_xml_len, data, data_len);
1051 pthread_cleanup_pop(1); // enc_xml
1052 if (!rc) {
1053 if (filename)
1054 g_lstat(filename, &crypto->st);
1056 memcpy(&crypto->hdr, &crypto->save.hdr, sizeof(file_header_t));
1060 g_free(data);
1061 return rc;
1064 void cleanup_save(struct save_s *save)
1066 if (!save)
1067 return;
1069 if (save->pkey)
1070 gcry_sexp_release(save->pkey);
1072 if (save->sigpkey)
1073 gcry_sexp_release(save->sigpkey);
1075 memset(save, 0, sizeof(struct save_s));
1078 /* Keep the agent ctx to retain pinentry options which will be freed in
1079 * cleanup_cb(). Also keep .pubkey since it may be needed for a SAVE. */
1080 void cleanup_crypto_stage1(struct crypto_s *cr)
1082 if (!cr)
1083 return;
1085 cleanup_save(&cr->save);
1087 if (cr->ciphertext_sexp)
1088 gcry_sexp_release(cr->ciphertext_sexp);
1090 if (cr->plaintext)
1091 gcry_free(cr->plaintext);
1093 g_free(cr->ciphertext);
1094 g_free(cr->filename);
1095 cr->filename = NULL;
1096 cr->ciphertext_sexp = NULL;
1097 cr->ciphertext = NULL;
1098 cr->ciphertext_len = 0;
1099 cr->plaintext = NULL;
1100 cr->plaintext_len = 0;
1103 void cleanup_crypto_stage2(struct crypto_s *cr)
1105 if (!cr)
1106 return;
1108 cleanup_crypto_stage1(cr);
1109 set_header_defaults(&cr->hdr);
1112 void cleanup_crypto(struct crypto_s **c)
1114 struct crypto_s *cr = *c;
1116 if (!cr)
1117 return;
1119 cleanup_crypto_stage2(cr);
1121 if (cr->pkey_sexp)
1122 gcry_sexp_release(cr->pkey_sexp);
1124 if (cr->sigpkey_sexp)
1125 gcry_sexp_release(cr->sigpkey_sexp);
1127 if (cr->agent)
1128 cleanup_agent(cr->agent);
1130 g_free(cr);
1131 *c = NULL;
1134 gpg_error_t init_client_crypto(struct crypto_s **crypto)
1136 struct crypto_s *new = g_malloc0(sizeof(struct crypto_s));
1137 gpg_error_t rc;
1139 if (!new) {
1140 log_write("%s(%i): %s", __FILE__, __LINE__, pwmd_strerror(GPG_ERR_ENOMEM));
1141 return GPG_ERR_ENOMEM;
1144 rc = agent_init(&new->agent);
1145 if (!rc) {
1146 rc = send_agent_common_options(new->agent);
1147 if (!rc)
1148 rc = set_pinentry_options(new->agent);
1151 if (rc) {
1152 g_free(new);
1153 return rc;
1156 set_header_defaults(&new->hdr);
1157 *crypto = new;
1158 return 0;
1161 gpg_error_t generate_key(struct crypto_s *crypto, gchar *sexpstr,
1162 gboolean empty, gboolean preset)
1164 gpg_error_t rc;
1165 gchar *pkey;
1166 gsize plen;
1168 if (crypto->save.s2k_count) {
1169 rc = send_to_agent(crypto->agent, NULL, NULL,
1170 "OPTION s2k-count=%lu", crypto->save.s2k_count);
1171 if (rc)
1172 return rc;
1175 if (!crypto->agent->inquire_cb)
1176 crypto->agent->inquire_cb = inquire_cb;
1178 rc = send_to_agent(crypto->agent, &pkey, &plen, "GENKEY %s%s",
1179 preset ? "--preset " : "",
1180 empty ? "--no-protection" : "");
1181 if (rc)
1182 return rc;
1184 if (crypto->save.pkey)
1185 gcry_sexp_release(crypto->save.pkey);
1187 crypto->save.pkey = NULL;
1188 rc = gcry_sexp_new(&crypto->save.pkey, pkey, plen, 1);
1189 if (!rc) {
1190 guchar grip[20];
1192 gcry_pk_get_keygrip(crypto->save.pkey, grip);
1193 gchar *hexgrip = bin2hex(grip, sizeof(grip));
1194 log_write1(_("Keygrip is %s"), hexgrip);
1195 g_free(hexgrip);
1197 if (!crypto->save.sigpkey) {
1198 gcry_sexp_build((gcry_sexp_t *)&crypto->save.sigpkey, NULL, "%S",
1199 crypto->save.pkey);
1203 xfree(pkey);
1204 return rc;
1207 gpg_error_t set_agent_option(struct agent_s *agent, const gchar *name,
1208 const gchar *value)
1210 return send_to_agent(agent, NULL, NULL, "OPTION %s=%s", name, value);
1213 gpg_error_t set_agent_passphrase(struct crypto_s *crypto, const gchar *key,
1214 gsize len)
1216 gchar *hexgrip;
1217 struct inquire_data_s idata;
1218 gpg_error_t rc;
1219 gint i;
1221 /* This is for use with key files or passphrases obtained from an inquire.
1222 * gpg-agent uses strings as passphrases and will truncate the passphrase
1223 * at the first encountered null byte. It's only a warning because the
1224 * passphrase may belong to a key shared outside of pwmd. */
1225 for (i = 0; i < len; i++) {
1226 if (key[i] == 0) {
1227 log_write(_("WARNING: keylen=%i, truncated to %i."), len, i);
1228 break;
1232 hexgrip = bin2hex(crypto->grip, 20);
1233 crypto->agent->inquire_cb = inquire_cb;
1234 crypto->agent->inquire_data = &idata;
1235 idata.crypto = crypto;
1236 idata.line = (gchar *)key,
1237 idata.len = len;
1238 idata.preset = TRUE;
1239 assuan_begin_confidential(crypto->agent->ctx);
1240 rc = send_to_agent(crypto->agent, NULL, NULL,
1241 "PRESET_PASSPHRASE --inquire %s -1", hexgrip);
1242 assuan_end_confidential(crypto->agent->ctx);
1243 idata.preset = FALSE;
1244 g_free(hexgrip);
1245 return rc;
1248 gpg_error_t set_pinentry_mode(struct agent_s *agent, const gchar *mode)
1250 return set_agent_option(agent, "pinentry-mode", mode);
1253 gpg_error_t get_pubkey_bin(struct crypto_s *crypto, const guchar *grip,
1254 gcry_sexp_t *result)
1256 gchar *hexgrip = bin2hex(grip, 20);
1257 gpg_error_t rc;
1259 if (!hexgrip)
1260 return GPG_ERR_ENOMEM;
1262 rc = get_pubkey(crypto, hexgrip, result);
1263 g_free(hexgrip);
1264 return rc;
1267 gpg_error_t get_pubkey(struct crypto_s *crypto, const gchar *grip,
1268 gcry_sexp_t *result)
1270 gchar *pkey = NULL;
1271 gsize plen;
1272 gpg_error_t rc;
1274 rc = send_to_agent(crypto->agent, &pkey, &plen, "READKEY %s", grip);
1275 if (!rc)
1276 rc = gcry_sexp_new(result, pkey, plen, 1);
1278 xfree(pkey);
1279 return rc;
1282 gpg_error_t set_pinentry_options(struct agent_s *agent)
1284 gpg_error_t rc = 0;
1286 if (getenv("DISPLAY")) {
1287 rc = set_agent_option(agent, "display", getenv("DISPLAY"));
1288 if (!rc) {
1289 g_free(agent->display);
1290 agent->display = g_strdup(getenv("DISPLAY"));
1293 else if (ttyname(STDOUT_FILENO)) {
1294 rc = set_agent_option(agent, "ttyname", ttyname(STDOUT_FILENO));
1295 if (!rc) {
1296 rc = set_agent_option(agent, "ttytype", getenv("TERM"));
1297 if (!rc) {
1298 g_free(agent->ttyname);
1299 g_free(agent->ttytype);
1300 agent->ttyname = g_strdup(ttyname(STDOUT_FILENO));
1301 agent->ttytype = g_strdup(getenv("TERM"));
1306 return rc;
1309 static gpg_error_t inquire_keyfile(gpointer user, const gchar *keyword)
1311 struct crypto_s *crypto = user;
1312 gchar *filename = crypto->agent->inquire_data2;
1313 gchar *params = crypto->agent->inquire_data3;
1314 gint fd;
1315 struct stat st;
1316 guchar *buf;
1317 gsize len;
1318 gpg_error_t rc;
1320 if (!g_strcmp0(keyword, "KEYPARAM"))
1321 return assuan_send_data(crypto->agent->ctx, params, strlen(params));
1323 // This function is only used when generating a new keypair.
1324 if (g_strcmp0(keyword, "NEW_PASSPHRASE"))
1325 return gpg_error(GPG_ERR_ASS_UNKNOWN_INQUIRE);
1327 if (stat(filename, &st) == -1)
1328 return gpg_error_from_syserror();
1330 if (crypto->agent->inquire_maxlen
1331 && st.st_size > crypto->agent->inquire_maxlen) {
1332 log_write(_("The passphrase is too large: have=%u, max=%u."),
1333 (unsigned)st.st_size, crypto->agent->inquire_maxlen);
1334 return GPG_ERR_TOO_LARGE;
1337 buf = gcry_malloc_secure(st.st_size);
1338 if (!buf)
1339 return GPG_ERR_ENOMEM;
1341 fd = open(filename, O_RDONLY);
1342 if (fd == -1)
1343 rc = gpg_error_from_syserror();
1344 else {
1345 len = read(fd, buf, st.st_size);
1346 if (len == st.st_size) {
1347 assuan_begin_confidential(crypto->agent->ctx);
1348 rc = assuan_send_data(crypto->agent->ctx, buf, len);
1349 assuan_end_confidential(crypto->agent->ctx);
1351 else if (len == -1)
1352 rc = gpg_error_from_syserror();
1353 else
1354 rc = GPG_ERR_BUFFER_TOO_SHORT;
1357 close(fd);
1358 gcry_free(buf);
1359 return rc;
1362 gpg_error_t export_common(struct crypto_s *crypto, const gchar *hexgrip,
1363 const gchar *sign_hexgrip, gboolean no_passphrase,
1364 const gpointer data, gsize datalen, const gchar *outfile,
1365 const gchar *keyparams, const gchar *keyfile)
1367 gpg_error_t rc = 0;
1369 if (sign_hexgrip) {
1370 if (crypto->sigpkey_sexp)
1371 gcry_sexp_release(crypto->sigpkey_sexp);
1373 crypto->sigpkey_sexp = NULL;
1374 rc = get_pubkey(crypto, sign_hexgrip, &crypto->save.sigpkey);
1375 if (rc)
1376 return rc;
1378 gcry_pk_get_keygrip(crypto->save.sigpkey, crypto->sign_grip);
1381 if (hexgrip) {
1382 rc = get_pubkey(crypto, hexgrip, &crypto->save.pkey);
1383 if (!rc)
1384 gcry_pk_get_keygrip(crypto->save.pkey, crypto->grip);
1386 else {
1387 struct inquire_data_s idata = {0};
1388 gchar *params = keyparams ? g_strdup(keyparams)
1389 : default_key_params(crypto);
1391 pthread_cleanup_push(g_free, params);
1392 log_write(_("Generating a new keypair ..."));
1393 if (keyfile) {
1394 log_write(N_("Using passphrase obtained from file '%s'"), keyfile);
1395 rc = set_pinentry_mode(crypto->agent, "loopback");
1396 crypto->agent->inquire_cb = inquire_keyfile;
1397 crypto->agent->inquire_data = crypto;
1398 crypto->agent->inquire_data2 = (gchar *)keyfile;
1399 crypto->agent->inquire_data3 = params;
1401 else {
1402 idata.line = params;
1403 idata.len = strlen(params);
1404 idata.crypto = crypto;
1405 crypto->agent->inquire_cb = inquire_cb;
1406 crypto->agent->inquire_data = &idata;
1409 if (!rc) {
1410 rc = generate_key(crypto, params, no_passphrase, TRUE);
1411 gcry_pk_get_keygrip(crypto->save.pkey, crypto->grip);
1414 (void)set_pinentry_mode(crypto->agent, "ask");
1415 pthread_cleanup_pop(1);
1418 if (!rc) {
1419 rc = encrypt_data_file(crypto, crypto->save.pkey, crypto->save.sigpkey,
1420 outfile, data, datalen);
1421 if (!rc) {
1422 gchar *tmp = bin2hex(crypto->grip, sizeof(crypto->grip));
1424 log_write(_("Success! Keygrip is %s."), tmp);
1425 rc = send_to_agent(crypto->agent, NULL, NULL,
1426 "CLEAR_PASSPHRASE --mode=normal %s", tmp);
1427 g_free(tmp);
1429 if (sign_hexgrip) {
1430 tmp = bin2hex(crypto->sign_grip, sizeof(crypto->sign_grip));
1431 log_write(_("Signed with keygrip %s."), tmp);
1432 g_free(tmp);
1437 return rc;
1440 gchar *default_key_params(struct crypto_s *crypto)
1442 gint len = get_key_file_integer(NULL, "nbits");
1443 gchar buf[32];
1444 gchar *algo = get_key_file_string(NULL, "algo");
1445 gchar *result;
1447 g_snprintf(buf, sizeof(buf), "%i", len);
1448 result = g_strdup_printf("(genkey (%s (nbits %i:%i)))", algo, strlen(buf),
1449 len);
1450 g_free(algo);
1451 return result;
1454 gpg_error_t agent_passwd(struct crypto_s *crypto)
1456 struct inquire_data_s idata = {0};
1457 gpg_error_t rc;
1458 gchar *tmp = bin2hex(crypto->grip, 20);
1460 idata.crypto = crypto;
1461 crypto->agent->inquire_cb = inquire_cb;
1462 crypto->agent->inquire_data = &idata;
1463 rc = send_to_agent(crypto->agent, NULL, NULL, "PASSWD --preset %s", tmp);
1464 g_free(tmp);
1465 return rc;