2009-05-15 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / g10 / call-agent.c
blob444048a47fbad995df2c96e2bd998654a7cbfae5
1 /* call-agent.c - Divert GPG operations to the agent.
2 * Copyright (C) 2001, 2002, 2003, 2006, 2007,
3 * 2008 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
7 * GnuPG 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 3 of the License, or
10 * (at your option) any later version.
12 * GnuPG 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 this program; if not, see <http://www.gnu.org/licenses/>.
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <unistd.h>
27 #include <time.h>
28 #include <assert.h>
29 #ifdef HAVE_LOCALE_H
30 #include <locale.h>
31 #endif
32 #include <assuan.h>
34 #include "gpg.h"
35 #include "util.h"
36 #include "membuf.h"
37 #include "options.h"
38 #include "i18n.h"
39 #include "asshelp.h"
40 #include "sysutils.h"
41 #include "call-agent.h"
43 #ifndef DBG_ASSUAN
44 # define DBG_ASSUAN 1
45 #endif
47 static assuan_context_t agent_ctx = NULL;
49 struct cipher_parm_s
51 assuan_context_t ctx;
52 const char *ciphertext;
53 size_t ciphertextlen;
56 struct writecert_parm_s
58 assuan_context_t ctx;
59 const unsigned char *certdata;
60 size_t certdatalen;
63 struct writekey_parm_s
65 assuan_context_t ctx;
66 const unsigned char *keydata;
67 size_t keydatalen;
70 struct genkey_parm_s
72 assuan_context_t ctx;
73 const char *sexp;
74 size_t sexplen;
79 /* Try to connect to the agent via socket or fork it off and work by
80 pipes. Handle the server's initial greeting */
81 static int
82 start_agent (void)
84 int rc;
86 if (agent_ctx)
87 return 0; /* Fixme: We need a context for each thread or serialize
88 the access to the agent. */
90 rc = start_new_gpg_agent (&agent_ctx,
91 GPG_ERR_SOURCE_DEFAULT,
92 opt.homedir,
93 opt.agent_program,
94 opt.display, opt.ttyname, opt.ttytype,
95 opt.lc_ctype, opt.lc_messages,
96 opt.xauthority, opt.pinentry_user_data,
97 opt.verbose, DBG_ASSUAN,
98 NULL, NULL);
99 if (!rc)
101 /* Tell the agent that we support Pinentry notifications. No
102 error checking so that it will work also with older
103 agents. */
104 assuan_transact (agent_ctx, "OPTION allow-pinentry-notify",
105 NULL, NULL, NULL, NULL, NULL, NULL);
108 return rc;
112 /* Return a new malloced string by unescaping the string S. Escaping
113 is percent escaping and '+'/space mapping. A binary nul will
114 silently be replaced by a 0xFF. Function returns NULL to indicate
115 an out of memory status. */
116 static char *
117 unescape_status_string (const unsigned char *s)
119 return percent_plus_unescape (s, 0xff);
123 /* Take a 20 byte hexencoded string and put it into the the provided
124 20 byte buffer FPR in binary format. */
125 static int
126 unhexify_fpr (const char *hexstr, unsigned char *fpr)
128 const char *s;
129 int n;
131 for (s=hexstr, n=0; hexdigitp (s); s++, n++)
133 if (*s || (n != 40))
134 return 0; /* no fingerprint (invalid or wrong length). */
135 n /= 2;
136 for (s=hexstr, n=0; *s; s += 2, n++)
137 fpr[n] = xtoi_2 (s);
138 return 1; /* okay */
141 /* Take the serial number from LINE and return it verbatim in a newly
142 allocated string. We make sure that only hex characters are
143 returned. */
144 static char *
145 store_serialno (const char *line)
147 const char *s;
148 char *p;
150 for (s=line; hexdigitp (s); s++)
152 p = xtrymalloc (s + 1 - line);
153 if (p)
155 memcpy (p, line, s-line);
156 p[s-line] = 0;
158 return p;
163 /* This is a dummy data line callback. */
164 static int
165 dummy_data_cb (void *opaque, const void *buffer, size_t length)
167 (void)opaque;
168 (void)buffer;
169 (void)length;
170 return 0;
174 /* This is the default inquiry callback. It mainly handles the
175 Pinentry notifications. */
176 static int
177 default_inq_cb (void *opaque, const char *line)
179 (void)opaque;
181 if (!strncmp (line, "PINENTRY_LAUNCHED", 17) && (line[17]==' '||!line[17]))
183 /* There is no working server mode yet thus we use
184 AllowSetForegroundWindow window right here. We might want to
185 do this anyway in case gpg is called on the console. */
186 gnupg_allow_set_foregound_window ((pid_t)strtoul (line+17, NULL, 10));
187 /* We do not pass errors to avoid breaking other code. */
189 else
190 log_debug ("ignoring gpg-agent inquiry `%s'\n", line);
192 return 0;
197 /* Release the card info structure INFO. */
198 void
199 agent_release_card_info (struct agent_card_info_s *info)
201 if (!info)
202 return;
204 xfree (info->serialno); info->serialno = NULL;
205 xfree (info->apptype); info->apptype = NULL;
206 xfree (info->disp_name); info->disp_name = NULL;
207 xfree (info->disp_lang); info->disp_lang = NULL;
208 xfree (info->pubkey_url); info->pubkey_url = NULL;
209 xfree (info->login_data); info->login_data = NULL;
210 info->cafpr1valid = info->cafpr2valid = info->cafpr3valid = 0;
211 info->fpr1valid = info->fpr2valid = info->fpr3valid = 0;
214 static int
215 learn_status_cb (void *opaque, const char *line)
217 struct agent_card_info_s *parm = opaque;
218 const char *keyword = line;
219 int keywordlen;
220 int i;
222 for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
224 while (spacep (line))
225 line++;
227 if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
229 xfree (parm->serialno);
230 parm->serialno = store_serialno (line);
231 parm->is_v2 = (strlen (parm->serialno) >= 16
232 && xtoi_2 (parm->serialno+12) >= 2 );
234 else if (keywordlen == 7 && !memcmp (keyword, "APPTYPE", keywordlen))
236 xfree (parm->apptype);
237 parm->apptype = unescape_status_string (line);
239 else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
241 xfree (parm->disp_name);
242 parm->disp_name = unescape_status_string (line);
244 else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen))
246 xfree (parm->disp_lang);
247 parm->disp_lang = unescape_status_string (line);
249 else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen))
251 parm->disp_sex = *line == '1'? 1 : *line == '2' ? 2: 0;
253 else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
255 xfree (parm->pubkey_url);
256 parm->pubkey_url = unescape_status_string (line);
258 else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen))
260 xfree (parm->login_data);
261 parm->login_data = unescape_status_string (line);
263 else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen))
265 parm->sig_counter = strtoul (line, NULL, 0);
267 else if (keywordlen == 10 && !memcmp (keyword, "CHV-STATUS", keywordlen))
269 char *p, *buf;
271 buf = p = unescape_status_string (line);
272 if (buf)
274 while (spacep (p))
275 p++;
276 parm->chv1_cached = atoi (p);
277 while (*p && !spacep (p))
278 p++;
279 while (spacep (p))
280 p++;
281 for (i=0; *p && i < 3; i++)
283 parm->chvmaxlen[i] = atoi (p);
284 while (*p && !spacep (p))
285 p++;
286 while (spacep (p))
287 p++;
289 for (i=0; *p && i < 3; i++)
291 parm->chvretry[i] = atoi (p);
292 while (*p && !spacep (p))
293 p++;
294 while (spacep (p))
295 p++;
297 xfree (buf);
300 else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
302 int no = atoi (line);
303 while (*line && !spacep (line))
304 line++;
305 while (spacep (line))
306 line++;
307 if (no == 1)
308 parm->fpr1valid = unhexify_fpr (line, parm->fpr1);
309 else if (no == 2)
310 parm->fpr2valid = unhexify_fpr (line, parm->fpr2);
311 else if (no == 3)
312 parm->fpr3valid = unhexify_fpr (line, parm->fpr3);
314 else if (keywordlen == 6 && !memcmp (keyword, "CA-FPR", keywordlen))
316 int no = atoi (line);
317 while (*line && !spacep (line))
318 line++;
319 while (spacep (line))
320 line++;
321 if (no == 1)
322 parm->cafpr1valid = unhexify_fpr (line, parm->cafpr1);
323 else if (no == 2)
324 parm->cafpr2valid = unhexify_fpr (line, parm->cafpr2);
325 else if (no == 3)
326 parm->cafpr3valid = unhexify_fpr (line, parm->cafpr3);
329 return 0;
332 /* Call the agent to learn about a smartcard */
334 agent_learn (struct agent_card_info_s *info)
336 int rc;
338 rc = start_agent ();
339 if (rc)
340 return rc;
342 memset (info, 0, sizeof *info);
343 rc = assuan_transact (agent_ctx, "LEARN --send",
344 dummy_data_cb, NULL, default_inq_cb, NULL,
345 learn_status_cb, info);
347 return rc;
350 /* Call the agent to retrieve a data object. This function returns
351 the data in the same structure as used by the learn command. It is
352 allowed to update such a structure using this commmand. */
354 agent_scd_getattr (const char *name, struct agent_card_info_s *info)
356 int rc;
357 char line[ASSUAN_LINELENGTH];
359 if (!*name)
360 return gpg_error (GPG_ERR_INV_VALUE);
362 /* We assume that NAME does not need escaping. */
363 if (12 + strlen (name) > DIM(line)-1)
364 return gpg_error (GPG_ERR_TOO_LARGE);
365 stpcpy (stpcpy (line, "SCD GETATTR "), name);
367 rc = start_agent ();
368 if (rc)
369 return rc;
371 rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, NULL,
372 learn_status_cb, info);
374 return rc;
378 /* Send an setattr command to the SCdaemon. SERIALNO is not actually
379 used here but required by gpg 1.4's implementation of this code in
380 cardglue.c. */
382 agent_scd_setattr (const char *name,
383 const unsigned char *value, size_t valuelen,
384 const char *serialno)
386 int rc;
387 char line[ASSUAN_LINELENGTH];
388 char *p;
390 (void)serialno;
392 if (!*name || !valuelen)
393 return gpg_error (GPG_ERR_INV_VALUE);
395 /* We assume that NAME does not need escaping. */
396 if (12 + strlen (name) > DIM(line)-1)
397 return gpg_error (GPG_ERR_TOO_LARGE);
399 p = stpcpy (stpcpy (line, "SCD SETATTR "), name);
400 *p++ = ' ';
401 for (; valuelen; value++, valuelen--)
403 if (p >= line + DIM(line)-5 )
404 return gpg_error (GPG_ERR_TOO_LARGE);
405 if (*value < ' ' || *value == '+' || *value == '%')
407 sprintf (p, "%%%02X", *value);
408 p += 3;
410 else if (*value == ' ')
411 *p++ = '+';
412 else
413 *p++ = *value;
415 *p = 0;
417 rc = start_agent ();
418 if (rc)
419 return rc;
421 rc = assuan_transact (agent_ctx, line, NULL, NULL,
422 default_inq_cb, NULL, NULL, NULL);
423 return rc;
428 /* Handle a CERTDATA inquiry. Note, we only send the data,
429 assuan_transact takes care of flushing and writing the END
430 command. */
431 static int
432 inq_writecert_parms (void *opaque, const char *line)
434 int rc;
435 struct writecert_parm_s *parm = opaque;
437 if (!strncmp (line, "CERTDATA", 8) && (line[8]==' '||!line[8]))
439 rc = assuan_send_data (parm->ctx, parm->certdata, parm->certdatalen);
441 else
442 rc = default_inq_cb (opaque, line);
444 return rc;
448 /* Send a WRITECERT command to the SCdaemon. */
449 int
450 agent_scd_writecert (const char *certidstr,
451 const unsigned char *certdata, size_t certdatalen)
453 int rc;
454 char line[ASSUAN_LINELENGTH];
455 struct writecert_parm_s parms;
457 rc = start_agent ();
458 if (rc)
459 return rc;
461 memset (&parms, 0, sizeof parms);
463 snprintf (line, DIM(line)-1, "SCD WRITECERT %s", certidstr);
464 line[DIM(line)-1] = 0;
465 parms.ctx = agent_ctx;
466 parms.certdata = certdata;
467 parms.certdatalen = certdatalen;
469 rc = assuan_transact (agent_ctx, line, NULL, NULL,
470 inq_writecert_parms, &parms, NULL, NULL);
472 return rc;
478 /* Handle a KEYDATA inquiry. Note, we only send the data,
479 assuan_transact takes care of flushing and writing the end */
480 static int
481 inq_writekey_parms (void *opaque, const char *line)
483 int rc;
484 struct writekey_parm_s *parm = opaque;
486 if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7]))
488 rc = assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen);
490 else
491 rc = default_inq_cb (opaque, line);
493 return rc;
497 /* Send a WRITEKEY command to the SCdaemon. */
498 int
499 agent_scd_writekey (int keyno, const char *serialno,
500 const unsigned char *keydata, size_t keydatalen)
502 int rc;
503 char line[ASSUAN_LINELENGTH];
504 struct writekey_parm_s parms;
506 (void)serialno;
508 rc = start_agent ();
509 if (rc)
510 return rc;
512 memset (&parms, 0, sizeof parms);
514 snprintf (line, DIM(line)-1, "SCD WRITEKEY --force OPENPGP.%d", keyno);
515 line[DIM(line)-1] = 0;
516 parms.ctx = agent_ctx;
517 parms.keydata = keydata;
518 parms.keydatalen = keydatalen;
520 rc = assuan_transact (agent_ctx, line, NULL, NULL,
521 inq_writekey_parms, &parms, NULL, NULL);
523 return rc;
529 /* Status callback for the SCD GENKEY command. */
530 static int
531 scd_genkey_cb (void *opaque, const char *line)
533 struct agent_card_genkey_s *parm = opaque;
534 const char *keyword = line;
535 int keywordlen;
536 gpg_error_t rc;
538 log_debug ("got status line `%s'\n", line);
539 for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
541 while (spacep (line))
542 line++;
544 if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
546 parm->fprvalid = unhexify_fpr (line, parm->fpr);
548 if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
550 gcry_mpi_t a;
551 const char *name = line;
553 while (*line && !spacep (line))
554 line++;
555 while (spacep (line))
556 line++;
558 rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, line, 0, NULL);
559 if (rc)
560 log_error ("error parsing received key data: %s\n", gpg_strerror (rc));
561 else if (*name == 'n' && spacep (name+1))
562 parm->n = a;
563 else if (*name == 'e' && spacep (name+1))
564 parm->e = a;
565 else
567 log_info ("unknown parameter name in received key data\n");
568 gcry_mpi_release (a);
571 else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
573 parm->created_at = (u32)strtoul (line, NULL, 10);
576 return 0;
579 /* Send a GENKEY command to the SCdaemon. SERIALNO is not used in
580 this implementation. If CREATEDATE has been given, it will be
581 passed to SCDAEMON so that the key can be created with this
582 timestamp; note the user needs to use the returned timestamp as old
583 versions of scddaemon don't support this option. */
585 agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
586 const char *serialno, u32 createtime)
588 int rc;
589 char line[ASSUAN_LINELENGTH];
590 gnupg_isotime_t tbuf;
592 (void)serialno;
594 rc = start_agent ();
595 if (rc)
596 return rc;
598 if (createtime)
599 epoch2isotime (tbuf, createtime);
600 else
601 *tbuf = 0;
603 memset (info, 0, sizeof *info);
604 snprintf (line, DIM(line)-1, "SCD GENKEY %s%s %s %d",
605 *tbuf? "--timestamp=":"", tbuf,
606 force? "--force":"",
607 keyno);
608 line[DIM(line)-1] = 0;
610 memset (info, 0, sizeof *info);
611 rc = assuan_transact (agent_ctx, line,
612 NULL, NULL, default_inq_cb, NULL,
613 scd_genkey_cb, info);
615 return rc;
619 static int
620 membuf_data_cb (void *opaque, const void *buffer, size_t length)
622 membuf_t *data = opaque;
624 if (buffer)
625 put_membuf (data, buffer, length);
626 return 0;
629 /* Send a sign command to the scdaemon via gpg-agent's pass thru
630 mechanism. */
632 agent_scd_pksign (const char *serialno, int hashalgo,
633 const unsigned char *indata, size_t indatalen,
634 unsigned char **r_buf, size_t *r_buflen)
636 int rc, i;
637 char *p, line[ASSUAN_LINELENGTH];
638 membuf_t data;
639 size_t len;
641 /* Note, hashalgo is not yet used but hardwired to SHA1 in SCdaemon. */
643 *r_buf = NULL;
644 *r_buflen = 0;
646 rc = start_agent ();
647 if (rc)
648 return rc;
650 if (indatalen*2 + 50 > DIM(line))
651 return gpg_error (GPG_ERR_GENERAL);
653 /* Send the serialno command to initialize the connection. We don't
654 care about the data returned. If the card has already been
655 initialized, this is a very fast command. We request the openpgp
656 card because that is waht we expect. */
657 rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
658 NULL, NULL, NULL, NULL, NULL, NULL);
659 if (rc)
660 return rc;
662 sprintf (line, "SCD SETDATA ");
663 p = line + strlen (line);
664 for (i=0; i < indatalen ; i++, p += 2 )
665 sprintf (p, "%02X", indata[i]);
666 rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
667 if (rc)
668 return rc;
670 init_membuf (&data, 1024);
671 #if 0
672 if (!hashalgo) /* Temporary test hack. */
673 snprintf (line, DIM(line)-1, "SCD PKAUTH %s", serialno);
674 else
675 #endif
676 snprintf (line, DIM(line)-1, "SCD PKSIGN %s%s",
677 hashalgo == GCRY_MD_RMD160? "--hash=rmd160 " : "",
678 serialno);
679 line[DIM(line)-1] = 0;
680 rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data,
681 default_inq_cb, NULL, NULL, NULL);
682 if (rc)
684 xfree (get_membuf (&data, &len));
685 return rc;
687 *r_buf = get_membuf (&data, r_buflen);
689 return 0;
693 /* Decrypt INDATA of length INDATALEN using the card identified by
694 SERIALNO. Return the plaintext in a nwly allocated buffer stored
695 at the address of R_BUF.
697 Note, we currently support only RSA or more exactly algorithms
698 taking one input data element. */
700 agent_scd_pkdecrypt (const char *serialno,
701 const unsigned char *indata, size_t indatalen,
702 unsigned char **r_buf, size_t *r_buflen)
704 int rc, i;
705 char *p, line[ASSUAN_LINELENGTH];
706 membuf_t data;
707 size_t len;
709 *r_buf = NULL;
710 rc = start_agent ();
711 if (rc)
712 return rc;
714 /* FIXME: use secure memory where appropriate */
715 if (indatalen*2 + 50 > DIM(line))
716 return gpg_error (GPG_ERR_GENERAL);
718 /* Send the serialno command to initialize the connection. We don't
719 care about the data returned. If the card has already been
720 initialized, this is a very fast command. We request the openpgp
721 card because that is waht we expect. */
722 rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
723 NULL, NULL, NULL, NULL, NULL, NULL);
724 if (rc)
725 return rc;
727 sprintf (line, "SCD SETDATA ");
728 p = line + strlen (line);
729 for (i=0; i < indatalen ; i++, p += 2 )
730 sprintf (p, "%02X", indata[i]);
731 rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
732 if (rc)
733 return rc;
735 init_membuf (&data, 1024);
736 snprintf (line, DIM(line)-1, "SCD PKDECRYPT %s", serialno);
737 line[DIM(line)-1] = 0;
738 rc = assuan_transact (agent_ctx, line,
739 membuf_data_cb, &data,
740 default_inq_cb, NULL, NULL, NULL);
741 if (rc)
743 xfree (get_membuf (&data, &len));
744 return rc;
746 *r_buf = get_membuf (&data, r_buflen);
747 if (!*r_buf)
748 return gpg_error (GPG_ERR_ENOMEM);
750 return 0;
754 /* Change the PIN of an OpenPGP card or reset the retry counter.
755 CHVNO 1: Change the PIN
756 2: For v1 cards: Same as 1.
757 For v2 cards: Reset the PIN using the Reset Code.
758 3: Change the admin PIN
759 101: Set a new PIN and reset the retry counter
760 102: For v1 cars: Same as 101.
761 For v2 cards: Set a new Reset Code.
762 SERIALNO is not used.
765 agent_scd_change_pin (int chvno, const char *serialno)
767 int rc;
768 char line[ASSUAN_LINELENGTH];
769 const char *reset = "";
771 (void)serialno;
773 if (chvno >= 100)
774 reset = "--reset";
775 chvno %= 100;
777 rc = start_agent ();
778 if (rc)
779 return rc;
781 snprintf (line, DIM(line)-1, "SCD PASSWD %s %d", reset, chvno);
782 line[DIM(line)-1] = 0;
783 rc = assuan_transact (agent_ctx, line, NULL, NULL,
784 default_inq_cb, NULL, NULL, NULL);
785 return rc;
789 /* Perform a CHECKPIN operation. SERIALNO should be the serial
790 number of the card - optionally followed by the fingerprint;
791 however the fingerprint is ignored here. */
793 agent_scd_checkpin (const char *serialno)
795 int rc;
796 char line[ASSUAN_LINELENGTH];
798 rc = start_agent ();
799 if (rc)
800 return rc;
802 snprintf (line, DIM(line)-1, "SCD CHECKPIN %s", serialno);
803 line[DIM(line)-1] = 0;
804 return assuan_transact (agent_ctx, line,
805 NULL, NULL,
806 default_inq_cb, NULL, NULL, NULL);
810 /* Dummy function, only used by the gpg 1.4 implementation. */
811 void
812 agent_clear_pin_cache (const char *sn)
814 (void)sn;
820 /* Note: All strings shall be UTF-8. On success the caller needs to
821 free the string stored at R_PASSPHRASE. On error NULL will be
822 stored at R_PASSPHRASE and an appropriate fpf error code
823 returned. */
824 gpg_error_t
825 agent_get_passphrase (const char *cache_id,
826 const char *err_msg,
827 const char *prompt,
828 const char *desc_msg,
829 int repeat,
830 char **r_passphrase)
832 int rc;
833 char line[ASSUAN_LINELENGTH];
834 char *arg1 = NULL;
835 char *arg2 = NULL;
836 char *arg3 = NULL;
837 char *arg4 = NULL;
838 membuf_t data;
840 *r_passphrase = NULL;
842 rc = start_agent ();
843 if (rc)
844 return rc;
846 /* Check that the gpg-agent understands the repeat option. */
847 if (assuan_transact (agent_ctx,
848 "GETINFO cmd_has_option GET_PASSPHRASE repeat",
849 NULL, NULL, NULL, NULL, NULL, NULL))
850 return gpg_error (GPG_ERR_NOT_SUPPORTED);
852 if (cache_id && *cache_id)
853 if (!(arg1 = percent_plus_escape (cache_id)))
854 goto no_mem;
855 if (err_msg && *err_msg)
856 if (!(arg2 = percent_plus_escape (err_msg)))
857 goto no_mem;
858 if (prompt && *prompt)
859 if (!(arg3 = percent_plus_escape (prompt)))
860 goto no_mem;
861 if (desc_msg && *desc_msg)
862 if (!(arg4 = percent_plus_escape (desc_msg)))
863 goto no_mem;
865 snprintf (line, DIM(line)-1,
866 "GET_PASSPHRASE --data --repeat=%d -- %s %s %s %s",
867 repeat,
868 arg1? arg1:"X",
869 arg2? arg2:"X",
870 arg3? arg3:"X",
871 arg4? arg4:"X");
872 line[DIM(line)-1] = 0;
873 xfree (arg1);
874 xfree (arg2);
875 xfree (arg3);
876 xfree (arg4);
878 init_membuf_secure (&data, 64);
879 rc = assuan_transact (agent_ctx, line,
880 membuf_data_cb, &data,
881 default_inq_cb, NULL, NULL, NULL);
883 if (rc)
884 xfree (get_membuf (&data, NULL));
885 else
887 put_membuf (&data, "", 1);
888 *r_passphrase = get_membuf (&data, NULL);
889 if (!*r_passphrase)
890 rc = gpg_error_from_syserror ();
892 return rc;
893 no_mem:
894 rc = gpg_error_from_syserror ();
895 xfree (arg1);
896 xfree (arg2);
897 xfree (arg3);
898 xfree (arg4);
899 return rc;
903 gpg_error_t
904 agent_clear_passphrase (const char *cache_id)
906 int rc;
907 char line[ASSUAN_LINELENGTH];
909 if (!cache_id || !*cache_id)
910 return 0;
912 rc = start_agent ();
913 if (rc)
914 return rc;
916 snprintf (line, DIM(line)-1, "CLEAR_PASSPHRASE %s", cache_id);
917 line[DIM(line)-1] = 0;
918 return assuan_transact (agent_ctx, line, NULL, NULL,
919 default_inq_cb, NULL, NULL, NULL);