app-openpgp changes
[gnupg.git] / g10 / call-agent.c
blob63919dd1f312a736df45cf97b676233ec74a8c95
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);
328 else if (keywordlen == 8 && !memcmp (keyword, "KEY-ATTR", keywordlen))
330 int keyno, algo, nbits;
332 sscanf (line, "%d %d %d", &keyno, &algo, &nbits);
333 keyno--;
334 if (keyno >= 0 && keyno < DIM (parm->key_attr))
336 parm->key_attr[keyno].algo = algo;
337 parm->key_attr[keyno].nbits = nbits;
341 return 0;
344 /* Call the agent to learn about a smartcard */
346 agent_learn (struct agent_card_info_s *info)
348 int rc;
350 rc = start_agent ();
351 if (rc)
352 return rc;
354 memset (info, 0, sizeof *info);
355 rc = assuan_transact (agent_ctx, "LEARN --send",
356 dummy_data_cb, NULL, default_inq_cb, NULL,
357 learn_status_cb, info);
358 /* Also try to get the key attributes. */
359 if (!rc)
360 agent_scd_getattr ("KEY-ATTR", info);
362 return rc;
365 /* Call the agent to retrieve a data object. This function returns
366 the data in the same structure as used by the learn command. It is
367 allowed to update such a structure using this commmand. */
369 agent_scd_getattr (const char *name, struct agent_card_info_s *info)
371 int rc;
372 char line[ASSUAN_LINELENGTH];
374 if (!*name)
375 return gpg_error (GPG_ERR_INV_VALUE);
377 /* We assume that NAME does not need escaping. */
378 if (12 + strlen (name) > DIM(line)-1)
379 return gpg_error (GPG_ERR_TOO_LARGE);
380 stpcpy (stpcpy (line, "SCD GETATTR "), name);
382 rc = start_agent ();
383 if (rc)
384 return rc;
386 rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, NULL,
387 learn_status_cb, info);
389 return rc;
393 /* Send an setattr command to the SCdaemon. SERIALNO is not actually
394 used here but required by gpg 1.4's implementation of this code in
395 cardglue.c. */
397 agent_scd_setattr (const char *name,
398 const unsigned char *value, size_t valuelen,
399 const char *serialno)
401 int rc;
402 char line[ASSUAN_LINELENGTH];
403 char *p;
405 (void)serialno;
407 if (!*name || !valuelen)
408 return gpg_error (GPG_ERR_INV_VALUE);
410 /* We assume that NAME does not need escaping. */
411 if (12 + strlen (name) > DIM(line)-1)
412 return gpg_error (GPG_ERR_TOO_LARGE);
414 p = stpcpy (stpcpy (line, "SCD SETATTR "), name);
415 *p++ = ' ';
416 for (; valuelen; value++, valuelen--)
418 if (p >= line + DIM(line)-5 )
419 return gpg_error (GPG_ERR_TOO_LARGE);
420 if (*value < ' ' || *value == '+' || *value == '%')
422 sprintf (p, "%%%02X", *value);
423 p += 3;
425 else if (*value == ' ')
426 *p++ = '+';
427 else
428 *p++ = *value;
430 *p = 0;
432 rc = start_agent ();
433 if (rc)
434 return rc;
436 rc = assuan_transact (agent_ctx, line, NULL, NULL,
437 default_inq_cb, NULL, NULL, NULL);
438 return rc;
443 /* Handle a CERTDATA inquiry. Note, we only send the data,
444 assuan_transact takes care of flushing and writing the END
445 command. */
446 static int
447 inq_writecert_parms (void *opaque, const char *line)
449 int rc;
450 struct writecert_parm_s *parm = opaque;
452 if (!strncmp (line, "CERTDATA", 8) && (line[8]==' '||!line[8]))
454 rc = assuan_send_data (parm->ctx, parm->certdata, parm->certdatalen);
456 else
457 rc = default_inq_cb (opaque, line);
459 return rc;
463 /* Send a WRITECERT command to the SCdaemon. */
464 int
465 agent_scd_writecert (const char *certidstr,
466 const unsigned char *certdata, size_t certdatalen)
468 int rc;
469 char line[ASSUAN_LINELENGTH];
470 struct writecert_parm_s parms;
472 rc = start_agent ();
473 if (rc)
474 return rc;
476 memset (&parms, 0, sizeof parms);
478 snprintf (line, DIM(line)-1, "SCD WRITECERT %s", certidstr);
479 line[DIM(line)-1] = 0;
480 parms.ctx = agent_ctx;
481 parms.certdata = certdata;
482 parms.certdatalen = certdatalen;
484 rc = assuan_transact (agent_ctx, line, NULL, NULL,
485 inq_writecert_parms, &parms, NULL, NULL);
487 return rc;
493 /* Handle a KEYDATA inquiry. Note, we only send the data,
494 assuan_transact takes care of flushing and writing the end */
495 static int
496 inq_writekey_parms (void *opaque, const char *line)
498 int rc;
499 struct writekey_parm_s *parm = opaque;
501 if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7]))
503 rc = assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen);
505 else
506 rc = default_inq_cb (opaque, line);
508 return rc;
512 /* Send a WRITEKEY command to the SCdaemon. */
513 int
514 agent_scd_writekey (int keyno, const char *serialno,
515 const unsigned char *keydata, size_t keydatalen)
517 int rc;
518 char line[ASSUAN_LINELENGTH];
519 struct writekey_parm_s parms;
521 (void)serialno;
523 rc = start_agent ();
524 if (rc)
525 return rc;
527 memset (&parms, 0, sizeof parms);
529 snprintf (line, DIM(line)-1, "SCD WRITEKEY --force OPENPGP.%d", keyno);
530 line[DIM(line)-1] = 0;
531 parms.ctx = agent_ctx;
532 parms.keydata = keydata;
533 parms.keydatalen = keydatalen;
535 rc = assuan_transact (agent_ctx, line, NULL, NULL,
536 inq_writekey_parms, &parms, NULL, NULL);
538 return rc;
544 /* Status callback for the SCD GENKEY command. */
545 static int
546 scd_genkey_cb (void *opaque, const char *line)
548 struct agent_card_genkey_s *parm = opaque;
549 const char *keyword = line;
550 int keywordlen;
551 gpg_error_t rc;
553 for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
555 while (spacep (line))
556 line++;
558 if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
560 parm->fprvalid = unhexify_fpr (line, parm->fpr);
562 if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
564 gcry_mpi_t a;
565 const char *name = line;
567 while (*line && !spacep (line))
568 line++;
569 while (spacep (line))
570 line++;
572 rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, line, 0, NULL);
573 if (rc)
574 log_error ("error parsing received key data: %s\n", gpg_strerror (rc));
575 else if (*name == 'n' && spacep (name+1))
576 parm->n = a;
577 else if (*name == 'e' && spacep (name+1))
578 parm->e = a;
579 else
581 log_info ("unknown parameter name in received key data\n");
582 gcry_mpi_release (a);
585 else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
587 parm->created_at = (u32)strtoul (line, NULL, 10);
590 return 0;
593 /* Send a GENKEY command to the SCdaemon. SERIALNO is not used in
594 this implementation. If CREATEDATE has been given, it will be
595 passed to SCDAEMON so that the key can be created with this
596 timestamp; note the user needs to use the returned timestamp as old
597 versions of scddaemon don't support this option. */
599 agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
600 const char *serialno, u32 createtime)
602 int rc;
603 char line[ASSUAN_LINELENGTH];
604 gnupg_isotime_t tbuf;
606 (void)serialno;
608 rc = start_agent ();
609 if (rc)
610 return rc;
612 if (createtime)
613 epoch2isotime (tbuf, createtime);
614 else
615 *tbuf = 0;
617 memset (info, 0, sizeof *info);
618 snprintf (line, DIM(line)-1, "SCD GENKEY %s%s %s %d",
619 *tbuf? "--timestamp=":"", tbuf,
620 force? "--force":"",
621 keyno);
622 line[DIM(line)-1] = 0;
624 memset (info, 0, sizeof *info);
625 rc = assuan_transact (agent_ctx, line,
626 NULL, NULL, default_inq_cb, NULL,
627 scd_genkey_cb, info);
629 return rc;
633 static int
634 membuf_data_cb (void *opaque, const void *buffer, size_t length)
636 membuf_t *data = opaque;
638 if (buffer)
639 put_membuf (data, buffer, length);
640 return 0;
643 /* Send a sign command to the scdaemon via gpg-agent's pass thru
644 mechanism. */
646 agent_scd_pksign (const char *serialno, int hashalgo,
647 const unsigned char *indata, size_t indatalen,
648 unsigned char **r_buf, size_t *r_buflen)
650 int rc, i;
651 char *p, line[ASSUAN_LINELENGTH];
652 membuf_t data;
653 size_t len;
655 /* Note, hashalgo is not yet used but hardwired to SHA1 in SCdaemon. */
657 *r_buf = NULL;
658 *r_buflen = 0;
660 rc = start_agent ();
661 if (rc)
662 return rc;
664 if (indatalen*2 + 50 > DIM(line))
665 return gpg_error (GPG_ERR_GENERAL);
667 /* Send the serialno command to initialize the connection. We don't
668 care about the data returned. If the card has already been
669 initialized, this is a very fast command. We request the openpgp
670 card because that is what we expect. */
671 rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
672 NULL, NULL, NULL, NULL, NULL, NULL);
673 if (rc)
674 return rc;
676 sprintf (line, "SCD SETDATA ");
677 p = line + strlen (line);
678 for (i=0; i < indatalen ; i++, p += 2 )
679 sprintf (p, "%02X", indata[i]);
680 rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
681 if (rc)
682 return rc;
684 init_membuf (&data, 1024);
685 #if 0
686 if (!hashalgo) /* Temporary test hack. */
687 snprintf (line, DIM(line)-1, "SCD PKAUTH %s", serialno);
688 else
689 #endif
690 snprintf (line, DIM(line)-1, "SCD PKSIGN %s%s",
691 hashalgo == GCRY_MD_RMD160? "--hash=rmd160 " : "",
692 serialno);
693 line[DIM(line)-1] = 0;
694 rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data,
695 default_inq_cb, NULL, NULL, NULL);
696 if (rc)
698 xfree (get_membuf (&data, &len));
699 return rc;
701 *r_buf = get_membuf (&data, r_buflen);
703 return 0;
707 /* Decrypt INDATA of length INDATALEN using the card identified by
708 SERIALNO. Return the plaintext in a nwly allocated buffer stored
709 at the address of R_BUF.
711 Note, we currently support only RSA or more exactly algorithms
712 taking one input data element. */
714 agent_scd_pkdecrypt (const char *serialno,
715 const unsigned char *indata, size_t indatalen,
716 unsigned char **r_buf, size_t *r_buflen)
718 int rc, i;
719 char *p, line[ASSUAN_LINELENGTH];
720 membuf_t data;
721 size_t len;
723 *r_buf = NULL;
724 rc = start_agent ();
725 if (rc)
726 return rc;
728 /* FIXME: use secure memory where appropriate */
729 if (indatalen*2 + 50 > DIM(line))
730 return gpg_error (GPG_ERR_GENERAL);
732 /* Send the serialno command to initialize the connection. We don't
733 care about the data returned. If the card has already been
734 initialized, this is a very fast command. We request the openpgp
735 card because that is what we expect. */
736 rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
737 NULL, NULL, NULL, NULL, NULL, NULL);
738 if (rc)
739 return rc;
741 sprintf (line, "SCD SETDATA ");
742 p = line + strlen (line);
743 for (i=0; i < indatalen ; i++, p += 2 )
744 sprintf (p, "%02X", indata[i]);
745 rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
746 if (rc)
747 return rc;
749 init_membuf (&data, 1024);
750 snprintf (line, DIM(line)-1, "SCD PKDECRYPT %s", serialno);
751 line[DIM(line)-1] = 0;
752 rc = assuan_transact (agent_ctx, line,
753 membuf_data_cb, &data,
754 default_inq_cb, NULL, NULL, NULL);
755 if (rc)
757 xfree (get_membuf (&data, &len));
758 return rc;
760 *r_buf = get_membuf (&data, r_buflen);
761 if (!*r_buf)
762 return gpg_error (GPG_ERR_ENOMEM);
764 return 0;
768 /* Change the PIN of an OpenPGP card or reset the retry counter.
769 CHVNO 1: Change the PIN
770 2: For v1 cards: Same as 1.
771 For v2 cards: Reset the PIN using the Reset Code.
772 3: Change the admin PIN
773 101: Set a new PIN and reset the retry counter
774 102: For v1 cars: Same as 101.
775 For v2 cards: Set a new Reset Code.
776 SERIALNO is not used.
779 agent_scd_change_pin (int chvno, const char *serialno)
781 int rc;
782 char line[ASSUAN_LINELENGTH];
783 const char *reset = "";
785 (void)serialno;
787 if (chvno >= 100)
788 reset = "--reset";
789 chvno %= 100;
791 rc = start_agent ();
792 if (rc)
793 return rc;
795 snprintf (line, DIM(line)-1, "SCD PASSWD %s %d", reset, chvno);
796 line[DIM(line)-1] = 0;
797 rc = assuan_transact (agent_ctx, line, NULL, NULL,
798 default_inq_cb, NULL, NULL, NULL);
799 return rc;
803 /* Perform a CHECKPIN operation. SERIALNO should be the serial
804 number of the card - optionally followed by the fingerprint;
805 however the fingerprint is ignored here. */
807 agent_scd_checkpin (const char *serialno)
809 int rc;
810 char line[ASSUAN_LINELENGTH];
812 rc = start_agent ();
813 if (rc)
814 return rc;
816 snprintf (line, DIM(line)-1, "SCD CHECKPIN %s", serialno);
817 line[DIM(line)-1] = 0;
818 return assuan_transact (agent_ctx, line,
819 NULL, NULL,
820 default_inq_cb, NULL, NULL, NULL);
824 /* Dummy function, only used by the gpg 1.4 implementation. */
825 void
826 agent_clear_pin_cache (const char *sn)
828 (void)sn;
834 /* Note: All strings shall be UTF-8. On success the caller needs to
835 free the string stored at R_PASSPHRASE. On error NULL will be
836 stored at R_PASSPHRASE and an appropriate fpf error code
837 returned. */
838 gpg_error_t
839 agent_get_passphrase (const char *cache_id,
840 const char *err_msg,
841 const char *prompt,
842 const char *desc_msg,
843 int repeat,
844 int check,
845 char **r_passphrase)
847 int rc;
848 char line[ASSUAN_LINELENGTH];
849 char *arg1 = NULL;
850 char *arg2 = NULL;
851 char *arg3 = NULL;
852 char *arg4 = NULL;
853 membuf_t data;
855 *r_passphrase = NULL;
857 rc = start_agent ();
858 if (rc)
859 return rc;
861 /* Check that the gpg-agent understands the repeat option. */
862 if (assuan_transact (agent_ctx,
863 "GETINFO cmd_has_option GET_PASSPHRASE repeat",
864 NULL, NULL, NULL, NULL, NULL, NULL))
865 return gpg_error (GPG_ERR_NOT_SUPPORTED);
867 if (cache_id && *cache_id)
868 if (!(arg1 = percent_plus_escape (cache_id)))
869 goto no_mem;
870 if (err_msg && *err_msg)
871 if (!(arg2 = percent_plus_escape (err_msg)))
872 goto no_mem;
873 if (prompt && *prompt)
874 if (!(arg3 = percent_plus_escape (prompt)))
875 goto no_mem;
876 if (desc_msg && *desc_msg)
877 if (!(arg4 = percent_plus_escape (desc_msg)))
878 goto no_mem;
880 snprintf (line, DIM(line)-1,
881 "GET_PASSPHRASE --data --repeat=%d%s -- %s %s %s %s",
882 repeat,
883 check? " --check --qualitybar":"",
884 arg1? arg1:"X",
885 arg2? arg2:"X",
886 arg3? arg3:"X",
887 arg4? arg4:"X");
888 line[DIM(line)-1] = 0;
889 xfree (arg1);
890 xfree (arg2);
891 xfree (arg3);
892 xfree (arg4);
894 init_membuf_secure (&data, 64);
895 rc = assuan_transact (agent_ctx, line,
896 membuf_data_cb, &data,
897 default_inq_cb, NULL, NULL, NULL);
899 if (rc)
900 xfree (get_membuf (&data, NULL));
901 else
903 put_membuf (&data, "", 1);
904 *r_passphrase = get_membuf (&data, NULL);
905 if (!*r_passphrase)
906 rc = gpg_error_from_syserror ();
908 return rc;
909 no_mem:
910 rc = gpg_error_from_syserror ();
911 xfree (arg1);
912 xfree (arg2);
913 xfree (arg3);
914 xfree (arg4);
915 return rc;
919 gpg_error_t
920 agent_clear_passphrase (const char *cache_id)
922 int rc;
923 char line[ASSUAN_LINELENGTH];
925 if (!cache_id || !*cache_id)
926 return 0;
928 rc = start_agent ();
929 if (rc)
930 return rc;
932 snprintf (line, DIM(line)-1, "CLEAR_PASSPHRASE %s", cache_id);
933 line[DIM(line)-1] = 0;
934 return assuan_transact (agent_ctx, line, NULL, NULL,
935 default_inq_cb, NULL, NULL, NULL);