2006-09-06 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / sm / call-agent.c
blob2ab52ab7c6c55c9098e5316bf7aa4d6212dfc68e
1 /* call-agent.c - divert operations to the agent
2 * Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19 * USA.
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <unistd.h>
28 #include <time.h>
29 #include <assert.h>
30 #ifdef HAVE_LOCALE_H
31 #include <locale.h>
32 #endif
34 #include "gpgsm.h"
35 #include <gcrypt.h>
36 #include <assuan.h>
37 #include "i18n.h"
38 #include "asshelp.h"
39 #include "keydb.h" /* fixme: Move this to import.c */
40 #include "../common/membuf.h"
43 static assuan_context_t agent_ctx = NULL;
44 static int force_pipe_server = 0;
46 struct cipher_parm_s
48 assuan_context_t ctx;
49 const unsigned char *ciphertext;
50 size_t ciphertextlen;
53 struct genkey_parm_s
55 assuan_context_t ctx;
56 const unsigned char *sexp;
57 size_t sexplen;
60 struct learn_parm_s
62 int error;
63 assuan_context_t ctx;
64 membuf_t *data;
69 /* Try to connect to the agent via socket or fork it off and work by
70 pipes. Handle the server's initial greeting */
71 static int
72 start_agent (ctrl_t ctrl)
74 int rc = 0;
75 char *infostr, *p;
76 assuan_context_t ctx;
78 if (agent_ctx)
79 return 0; /* fixme: We need a context for each thread or serialize
80 the access to the agent (which is suitable given that
81 the agent is not MT. */
83 infostr = force_pipe_server? NULL : getenv ("GPG_AGENT_INFO");
84 if (!infostr || !*infostr)
86 const char *pgmname;
87 const char *argv[3];
88 char *sockname;
89 int no_close_list[3];
90 int i;
92 /* First check whether we can connect at the standard
93 socket. */
94 sockname = make_filename (opt.homedir, "S.gpg-agent", NULL);
95 rc = assuan_socket_connect (&ctx, sockname, 0);
96 xfree (sockname);
98 if (rc)
100 /* With no success start a new server. */
101 if (opt.verbose)
102 log_info (_("no running gpg-agent - starting one\n"));
104 gpgsm_status (ctrl, STATUS_PROGRESS, "starting_agent ? 0 0");
106 if (fflush (NULL))
108 gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
109 log_error ("error flushing pending output: %s\n",
110 strerror (errno));
111 return tmperr;
114 if (!opt.agent_program || !*opt.agent_program)
115 opt.agent_program = GNUPG_DEFAULT_AGENT;
116 if ( !(pgmname = strrchr (opt.agent_program, '/')))
117 pgmname = opt.agent_program;
118 else
119 pgmname++;
121 argv[0] = pgmname;
122 argv[1] = "--server";
123 argv[2] = NULL;
125 i=0;
126 if (log_get_fd () != -1)
127 no_close_list[i++] = log_get_fd ();
128 no_close_list[i++] = fileno (stderr);
129 no_close_list[i] = -1;
131 /* Connect to the agent and perform initial handshaking. */
132 rc = assuan_pipe_connect (&ctx, opt.agent_program, argv,
133 no_close_list);
136 else
138 int prot;
139 int pid;
141 infostr = xstrdup (infostr);
142 if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr)
144 log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
145 xfree (infostr);
146 force_pipe_server = 1;
147 return start_agent (ctrl);
149 *p++ = 0;
150 pid = atoi (p);
151 while (*p && *p != PATHSEP_C)
152 p++;
153 prot = *p? atoi (p+1) : 0;
154 if (prot != 1)
156 log_error (_("gpg-agent protocol version %d is not supported\n"),
157 prot);
158 xfree (infostr);
159 force_pipe_server = 1;
160 return start_agent (ctrl);
163 rc = assuan_socket_connect (&ctx, infostr, pid);
164 xfree (infostr);
165 if (gpg_err_code (rc) == GPG_ERR_ASS_CONNECT_FAILED)
167 log_error (_("can't connect to the agent - trying fall back\n"));
168 force_pipe_server = 1;
169 return start_agent (ctrl);
173 if (rc)
175 log_error ("can't connect to the agent: %s\n", gpg_strerror (rc));
176 return gpg_error (GPG_ERR_NO_AGENT);
178 agent_ctx = ctx;
180 if (DBG_ASSUAN)
181 log_debug ("connection to agent established\n");
183 rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
184 if (rc)
185 return rc;
187 return send_pinentry_environment (agent_ctx, GPG_ERR_SOURCE_DEFAULT,
188 opt.display, opt.ttyname, opt.ttytype,
189 opt.lc_ctype, opt.lc_messages);
193 static int
194 membuf_data_cb (void *opaque, const void *buffer, size_t length)
196 membuf_t *data = opaque;
198 if (buffer)
199 put_membuf (data, buffer, length);
200 return 0;
206 /* Call the agent to do a sign operation using the key identified by
207 the hex string KEYGRIP. */
209 gpgsm_agent_pksign (ctrl_t ctrl, const char *keygrip, const char *desc,
210 unsigned char *digest, size_t digestlen, int digestalgo,
211 unsigned char **r_buf, size_t *r_buflen )
213 int rc, i;
214 char *p, line[ASSUAN_LINELENGTH];
215 membuf_t data;
216 size_t len;
218 *r_buf = NULL;
219 rc = start_agent (ctrl);
220 if (rc)
221 return rc;
223 if (digestlen*2 + 50 > DIM(line))
224 return gpg_error (GPG_ERR_GENERAL);
226 rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
227 if (rc)
228 return rc;
230 snprintf (line, DIM(line)-1, "SIGKEY %s", keygrip);
231 line[DIM(line)-1] = 0;
232 rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
233 if (rc)
234 return rc;
236 if (desc)
238 snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
239 line[DIM(line)-1] = 0;
240 rc = assuan_transact (agent_ctx, line,
241 NULL, NULL, NULL, NULL, NULL, NULL);
242 if (rc)
243 return rc;
246 sprintf (line, "SETHASH %d ", digestalgo);
247 p = line + strlen (line);
248 for (i=0; i < digestlen ; i++, p += 2 )
249 sprintf (p, "%02X", digest[i]);
250 rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
251 if (rc)
252 return rc;
254 init_membuf (&data, 1024);
255 rc = assuan_transact (agent_ctx, "PKSIGN",
256 membuf_data_cb, &data, NULL, NULL, NULL, NULL);
257 if (rc)
259 xfree (get_membuf (&data, &len));
260 return rc;
262 *r_buf = get_membuf (&data, r_buflen);
264 if (!gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL))
266 xfree (*r_buf); *r_buf = NULL;
267 return gpg_error (GPG_ERR_INV_VALUE);
270 return *r_buf? 0 : out_of_core ();
276 /* Handle a CIPHERTEXT inquiry. Note, we only send the data,
277 assuan_transact talkes care of flushing and writing the end */
278 static int
279 inq_ciphertext_cb (void *opaque, const char *keyword)
281 struct cipher_parm_s *parm = opaque;
282 int rc;
284 assuan_begin_confidential (parm->ctx);
285 rc = assuan_send_data (parm->ctx, parm->ciphertext, parm->ciphertextlen);
286 assuan_end_confidential (parm->ctx);
287 return rc;
291 /* Call the agent to do a decrypt operation using the key identified by
292 the hex string KEYGRIP. */
294 gpgsm_agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
295 ksba_const_sexp_t ciphertext,
296 char **r_buf, size_t *r_buflen )
298 int rc;
299 char line[ASSUAN_LINELENGTH];
300 membuf_t data;
301 struct cipher_parm_s cipher_parm;
302 size_t n, len;
303 char *p, *buf, *endp;
304 size_t ciphertextlen;
306 if (!keygrip || strlen(keygrip) != 40 || !ciphertext || !r_buf || !r_buflen)
307 return gpg_error (GPG_ERR_INV_VALUE);
308 *r_buf = NULL;
310 ciphertextlen = gcry_sexp_canon_len (ciphertext, 0, NULL, NULL);
311 if (!ciphertextlen)
312 return gpg_error (GPG_ERR_INV_VALUE);
314 rc = start_agent (ctrl);
315 if (rc)
316 return rc;
318 rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
319 if (rc)
320 return rc;
322 assert ( DIM(line) >= 50 );
323 snprintf (line, DIM(line)-1, "SETKEY %s", keygrip);
324 line[DIM(line)-1] = 0;
325 rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
326 if (rc)
327 return rc;
329 if (desc)
331 snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
332 line[DIM(line)-1] = 0;
333 rc = assuan_transact (agent_ctx, line,
334 NULL, NULL, NULL, NULL, NULL, NULL);
335 if (rc)
336 return rc;
339 init_membuf (&data, 1024);
340 cipher_parm.ctx = agent_ctx;
341 cipher_parm.ciphertext = ciphertext;
342 cipher_parm.ciphertextlen = ciphertextlen;
343 rc = assuan_transact (agent_ctx, "PKDECRYPT",
344 membuf_data_cb, &data,
345 inq_ciphertext_cb, &cipher_parm, NULL, NULL);
346 if (rc)
348 xfree (get_membuf (&data, &len));
349 return rc;
352 put_membuf (&data, "", 1); /* Make sure it is 0 terminated. */
353 buf = get_membuf (&data, &len);
354 if (!buf)
355 return gpg_error (GPG_ERR_ENOMEM);
356 assert (len); /* (we forced Nul termination.) */
358 if (*buf == '(')
360 if (len < 13 || memcmp (buf, "(5:value", 8) ) /* "(5:valueN:D)\0" */
361 return gpg_error (GPG_ERR_INV_SEXP);
362 len -= 11; /* Count only the data of the second part. */
363 p = buf + 8; /* Skip leading parenthesis and the value tag. */
365 else
367 /* For compatibility with older gpg-agents handle the old style
368 incomplete S-exps. */
369 len--; /* Do not count the Nul. */
370 p = buf;
373 n = strtoul (p, &endp, 10);
374 if (!n || *endp != ':')
375 return gpg_error (GPG_ERR_INV_SEXP);
376 endp++;
377 if (endp-p+n > len)
378 return gpg_error (GPG_ERR_INV_SEXP); /* Oops: Inconsistent S-Exp. */
380 memmove (buf, endp, n);
382 *r_buflen = n;
383 *r_buf = buf;
384 return 0;
391 /* Handle a KEYPARMS inquiry. Note, we only send the data,
392 assuan_transact takes care of flushing and writing the end */
393 static int
394 inq_genkey_parms (void *opaque, const char *keyword)
396 struct genkey_parm_s *parm = opaque;
397 int rc;
399 rc = assuan_send_data (parm->ctx, parm->sexp, parm->sexplen);
400 return rc;
405 /* Call the agent to generate a newkey */
407 gpgsm_agent_genkey (ctrl_t ctrl,
408 ksba_const_sexp_t keyparms, ksba_sexp_t *r_pubkey)
410 int rc;
411 struct genkey_parm_s gk_parm;
412 membuf_t data;
413 size_t len;
414 unsigned char *buf;
416 *r_pubkey = NULL;
417 rc = start_agent (ctrl);
418 if (rc)
419 return rc;
421 rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
422 if (rc)
423 return rc;
425 init_membuf (&data, 1024);
426 gk_parm.ctx = agent_ctx;
427 gk_parm.sexp = keyparms;
428 gk_parm.sexplen = gcry_sexp_canon_len (keyparms, 0, NULL, NULL);
429 if (!gk_parm.sexplen)
430 return gpg_error (GPG_ERR_INV_VALUE);
431 rc = assuan_transact (agent_ctx, "GENKEY",
432 membuf_data_cb, &data,
433 inq_genkey_parms, &gk_parm, NULL, NULL);
434 if (rc)
436 xfree (get_membuf (&data, &len));
437 return rc;
439 buf = get_membuf (&data, &len);
440 if (!buf)
441 return gpg_error (GPG_ERR_ENOMEM);
442 if (!gcry_sexp_canon_len (buf, len, NULL, NULL))
444 xfree (buf);
445 return gpg_error (GPG_ERR_INV_SEXP);
447 *r_pubkey = buf;
448 return 0;
452 /* Call the agent to read the public key part for a given keygrip. */
454 gpgsm_agent_readkey (ctrl_t ctrl, const char *hexkeygrip,
455 ksba_sexp_t *r_pubkey)
457 int rc;
458 membuf_t data;
459 size_t len;
460 unsigned char *buf;
461 char line[ASSUAN_LINELENGTH];
463 *r_pubkey = NULL;
464 rc = start_agent (ctrl);
465 if (rc)
466 return rc;
468 rc = assuan_transact (agent_ctx, "RESET",NULL, NULL, NULL, NULL, NULL, NULL);
469 if (rc)
470 return rc;
472 snprintf (line, DIM(line)-1, "READKEY %s", hexkeygrip);
473 line[DIM(line)-1] = 0;
475 init_membuf (&data, 1024);
476 rc = assuan_transact (agent_ctx, line,
477 membuf_data_cb, &data,
478 NULL, NULL, NULL, NULL);
479 if (rc)
481 xfree (get_membuf (&data, &len));
482 return rc;
484 buf = get_membuf (&data, &len);
485 if (!buf)
486 return gpg_error (GPG_ERR_ENOMEM);
487 if (!gcry_sexp_canon_len (buf, len, NULL, NULL))
489 xfree (buf);
490 return gpg_error (GPG_ERR_INV_SEXP);
492 *r_pubkey = buf;
493 return 0;
497 /* Ask the agent whether the certificate is in the list of trusted
498 keys */
500 gpgsm_agent_istrusted (ctrl_t ctrl, ksba_cert_t cert)
502 int rc;
503 char *fpr;
504 char line[ASSUAN_LINELENGTH];
506 rc = start_agent (ctrl);
507 if (rc)
508 return rc;
510 fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
511 if (!fpr)
513 log_error ("error getting the fingerprint\n");
514 return gpg_error (GPG_ERR_GENERAL);
517 snprintf (line, DIM(line)-1, "ISTRUSTED %s", fpr);
518 line[DIM(line)-1] = 0;
519 xfree (fpr);
521 rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
522 return rc;
525 /* Ask the agent to mark CERT as a trusted Root-CA one */
527 gpgsm_agent_marktrusted (ctrl_t ctrl, ksba_cert_t cert)
529 int rc;
530 char *fpr, *dn;
531 char line[ASSUAN_LINELENGTH];
533 rc = start_agent (ctrl);
534 if (rc)
535 return rc;
537 fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
538 if (!fpr)
540 log_error ("error getting the fingerprint\n");
541 return gpg_error (GPG_ERR_GENERAL);
544 dn = ksba_cert_get_issuer (cert, 0);
545 if (!dn)
547 xfree (fpr);
548 return gpg_error (GPG_ERR_GENERAL);
550 snprintf (line, DIM(line)-1, "MARKTRUSTED %s S %s", fpr, dn);
551 line[DIM(line)-1] = 0;
552 ksba_free (dn);
553 xfree (fpr);
555 rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
556 return rc;
561 /* Ask the agent whether the a corresponding secret key is available
562 for the given keygrip */
564 gpgsm_agent_havekey (ctrl_t ctrl, const char *hexkeygrip)
566 int rc;
567 char line[ASSUAN_LINELENGTH];
569 rc = start_agent (ctrl);
570 if (rc)
571 return rc;
573 if (!hexkeygrip || strlen (hexkeygrip) != 40)
574 return gpg_error (GPG_ERR_INV_VALUE);
576 snprintf (line, DIM(line)-1, "HAVEKEY %s", hexkeygrip);
577 line[DIM(line)-1] = 0;
579 rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
580 return rc;
584 static int
585 learn_cb (void *opaque, const void *buffer, size_t length)
587 struct learn_parm_s *parm = opaque;
588 size_t len;
589 char *buf;
590 ksba_cert_t cert;
591 int rc;
593 if (parm->error)
594 return 0;
596 if (buffer)
598 put_membuf (parm->data, buffer, length);
599 return 0;
601 /* END encountered - process what we have */
602 buf = get_membuf (parm->data, &len);
603 if (!buf)
605 parm->error = gpg_error (GPG_ERR_ENOMEM);
606 return 0;
610 /* FIXME: this should go into import.c */
611 rc = ksba_cert_new (&cert);
612 if (rc)
614 parm->error = rc;
615 return 0;
617 rc = ksba_cert_init_from_mem (cert, buf, len);
618 if (rc)
620 log_error ("failed to parse a certificate: %s\n", gpg_strerror (rc));
621 ksba_cert_release (cert);
622 parm->error = rc;
623 return 0;
626 rc = gpgsm_basic_cert_check (cert);
627 if (gpg_err_code (rc) == GPG_ERR_MISSING_CERT)
628 { /* For later use we store it in the ephemeral database. */
629 log_info ("issuer certificate missing - storing as ephemeral\n");
630 keydb_store_cert (cert, 1, NULL);
632 else if (rc)
633 log_error ("invalid certificate: %s\n", gpg_strerror (rc));
634 else
636 int existed;
638 if (!keydb_store_cert (cert, 0, &existed))
640 if (opt.verbose > 1 && existed)
641 log_info ("certificate already in DB\n");
642 else if (opt.verbose && !existed)
643 log_info ("certificate imported\n");
647 ksba_cert_release (cert);
648 init_membuf (parm->data, 4096);
649 return 0;
652 /* Call the agent to learn about a smartcard */
654 gpgsm_agent_learn (ctrl_t ctrl)
656 int rc;
657 struct learn_parm_s learn_parm;
658 membuf_t data;
659 size_t len;
661 rc = start_agent (ctrl);
662 if (rc)
663 return rc;
665 init_membuf (&data, 4096);
666 learn_parm.error = 0;
667 learn_parm.ctx = agent_ctx;
668 learn_parm.data = &data;
669 rc = assuan_transact (agent_ctx, "LEARN --send",
670 learn_cb, &learn_parm,
671 NULL, NULL, NULL, NULL);
672 xfree (get_membuf (&data, &len));
673 if (rc)
674 return rc;
675 return learn_parm.error;
679 /* Ask the agent to change the passphrase of the key identified by
680 HEXKEYGRIP. If DESC is not NULL, display instead of the default
681 description message. */
683 gpgsm_agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc)
685 int rc;
686 char line[ASSUAN_LINELENGTH];
688 rc = start_agent (ctrl);
689 if (rc)
690 return rc;
692 if (!hexkeygrip || strlen (hexkeygrip) != 40)
693 return gpg_error (GPG_ERR_INV_VALUE);
695 if (desc)
697 snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
698 line[DIM(line)-1] = 0;
699 rc = assuan_transact (agent_ctx, line,
700 NULL, NULL, NULL, NULL, NULL, NULL);
701 if (rc)
702 return rc;
705 snprintf (line, DIM(line)-1, "PASSWD %s", hexkeygrip);
706 line[DIM(line)-1] = 0;
708 rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
709 return rc;
714 /* Ask the agent to pop up a confirmation dialog with the text DESC
715 and an okay and cancel button. */
716 gpg_error_t
717 gpgsm_agent_get_confirmation (ctrl_t ctrl, const char *desc)
719 int rc;
720 char line[ASSUAN_LINELENGTH];
722 rc = start_agent (ctrl);
723 if (rc)
724 return rc;
726 snprintf (line, DIM(line)-1, "GET_CONFIRMATION %s", desc);
727 line[DIM(line)-1] = 0;
729 rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
730 return rc;