Print NO_SECKEY status line in gpgsm.
[gnupg.git] / g10 / call-agent.c
blobb6c61aa0ee8b6d165c947cc560595b2270717c46
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 char *buffer, *d;
121 buffer = d = xtrymalloc (strlen (s)+1);
122 if (!buffer)
123 return NULL;
124 while (*s)
126 if (*s == '%' && s[1] && s[2])
128 s++;
129 *d = xtoi_2 (s);
130 if (!*d)
131 *d = '\xff';
132 d++;
133 s += 2;
135 else if (*s == '+')
137 *d++ = ' ';
138 s++;
140 else
141 *d++ = *s++;
143 *d = 0;
144 return buffer;
148 /* Take a 20 byte hexencoded string and put it into the the provided
149 20 byte buffer FPR in binary format. */
150 static int
151 unhexify_fpr (const char *hexstr, unsigned char *fpr)
153 const char *s;
154 int n;
156 for (s=hexstr, n=0; hexdigitp (s); s++, n++)
158 if (*s || (n != 40))
159 return 0; /* no fingerprint (invalid or wrong length). */
160 n /= 2;
161 for (s=hexstr, n=0; *s; s += 2, n++)
162 fpr[n] = xtoi_2 (s);
163 return 1; /* okay */
166 /* Take the serial number from LINE and return it verbatim in a newly
167 allocated string. We make sure that only hex characters are
168 returned. */
169 static char *
170 store_serialno (const char *line)
172 const char *s;
173 char *p;
175 for (s=line; hexdigitp (s); s++)
177 p = xtrymalloc (s + 1 - line);
178 if (p)
180 memcpy (p, line, s-line);
181 p[s-line] = 0;
183 return p;
188 /* This is a dummy data line callback. */
189 static int
190 dummy_data_cb (void *opaque, const void *buffer, size_t length)
192 (void)opaque;
193 (void)buffer;
194 (void)length;
195 return 0;
199 /* This is the default inquiry callback. It mainly handles the
200 Pinentry notifications. */
201 static int
202 default_inq_cb (void *opaque, const char *line)
204 (void)opaque;
206 if (!strncmp (line, "PINENTRY_LAUNCHED", 17) && (line[17]==' '||!line[17]))
208 /* There is no working server mode yet thus we use
209 AllowSetForegroundWindow window right here. We might want to
210 do this anyway in case gpg is called on the console. */
211 gnupg_allow_set_foregound_window ((pid_t)strtoul (line+17, NULL, 10));
212 /* We do not pass errors to avoid breaking other code. */
214 else
215 log_debug ("ignoring gpg-agent inquiry `%s'\n", line);
217 return 0;
222 /* Release the card info structure INFO. */
223 void
224 agent_release_card_info (struct agent_card_info_s *info)
226 if (!info)
227 return;
229 xfree (info->serialno); info->serialno = NULL;
230 xfree (info->apptype); info->apptype = NULL;
231 xfree (info->disp_name); info->disp_name = NULL;
232 xfree (info->disp_lang); info->disp_lang = NULL;
233 xfree (info->pubkey_url); info->pubkey_url = NULL;
234 xfree (info->login_data); info->login_data = NULL;
235 info->cafpr1valid = info->cafpr2valid = info->cafpr3valid = 0;
236 info->fpr1valid = info->fpr2valid = info->fpr3valid = 0;
239 static int
240 learn_status_cb (void *opaque, const char *line)
242 struct agent_card_info_s *parm = opaque;
243 const char *keyword = line;
244 int keywordlen;
245 int i;
247 for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
249 while (spacep (line))
250 line++;
252 if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
254 xfree (parm->serialno);
255 parm->serialno = store_serialno (line);
256 parm->is_v2 = (strlen (parm->serialno) >= 16
257 && xtoi_2 (parm->serialno+12) >= 2 );
259 else if (keywordlen == 7 && !memcmp (keyword, "APPTYPE", keywordlen))
261 xfree (parm->apptype);
262 parm->apptype = unescape_status_string (line);
264 else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
266 xfree (parm->disp_name);
267 parm->disp_name = unescape_status_string (line);
269 else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen))
271 xfree (parm->disp_lang);
272 parm->disp_lang = unescape_status_string (line);
274 else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen))
276 parm->disp_sex = *line == '1'? 1 : *line == '2' ? 2: 0;
278 else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
280 xfree (parm->pubkey_url);
281 parm->pubkey_url = unescape_status_string (line);
283 else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen))
285 xfree (parm->login_data);
286 parm->login_data = unescape_status_string (line);
288 else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen))
290 parm->sig_counter = strtoul (line, NULL, 0);
292 else if (keywordlen == 10 && !memcmp (keyword, "CHV-STATUS", keywordlen))
294 char *p, *buf;
296 buf = p = unescape_status_string (line);
297 if (buf)
299 while (spacep (p))
300 p++;
301 parm->chv1_cached = atoi (p);
302 while (*p && !spacep (p))
303 p++;
304 while (spacep (p))
305 p++;
306 for (i=0; *p && i < 3; i++)
308 parm->chvmaxlen[i] = atoi (p);
309 while (*p && !spacep (p))
310 p++;
311 while (spacep (p))
312 p++;
314 for (i=0; *p && i < 3; i++)
316 parm->chvretry[i] = atoi (p);
317 while (*p && !spacep (p))
318 p++;
319 while (spacep (p))
320 p++;
322 xfree (buf);
325 else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
327 int no = atoi (line);
328 while (*line && !spacep (line))
329 line++;
330 while (spacep (line))
331 line++;
332 if (no == 1)
333 parm->fpr1valid = unhexify_fpr (line, parm->fpr1);
334 else if (no == 2)
335 parm->fpr2valid = unhexify_fpr (line, parm->fpr2);
336 else if (no == 3)
337 parm->fpr3valid = unhexify_fpr (line, parm->fpr3);
339 else if (keywordlen == 6 && !memcmp (keyword, "CA-FPR", keywordlen))
341 int no = atoi (line);
342 while (*line && !spacep (line))
343 line++;
344 while (spacep (line))
345 line++;
346 if (no == 1)
347 parm->cafpr1valid = unhexify_fpr (line, parm->cafpr1);
348 else if (no == 2)
349 parm->cafpr2valid = unhexify_fpr (line, parm->cafpr2);
350 else if (no == 3)
351 parm->cafpr3valid = unhexify_fpr (line, parm->cafpr3);
354 return 0;
357 /* Call the agent to learn about a smartcard */
359 agent_learn (struct agent_card_info_s *info)
361 int rc;
363 rc = start_agent ();
364 if (rc)
365 return rc;
367 memset (info, 0, sizeof *info);
368 rc = assuan_transact (agent_ctx, "LEARN --send",
369 dummy_data_cb, NULL, default_inq_cb, NULL,
370 learn_status_cb, info);
372 return rc;
375 /* Call the agent to retrieve a data object. This function returns
376 the data in the same structure as used by the learn command. It is
377 allowed to update such a structure using this commmand. */
379 agent_scd_getattr (const char *name, struct agent_card_info_s *info)
381 int rc;
382 char line[ASSUAN_LINELENGTH];
384 if (!*name)
385 return gpg_error (GPG_ERR_INV_VALUE);
387 /* We assume that NAME does not need escaping. */
388 if (12 + strlen (name) > DIM(line)-1)
389 return gpg_error (GPG_ERR_TOO_LARGE);
390 stpcpy (stpcpy (line, "SCD GETATTR "), name);
392 rc = start_agent ();
393 if (rc)
394 return rc;
396 rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, NULL,
397 learn_status_cb, info);
399 return rc;
403 /* Send an setattr command to the SCdaemon. SERIALNO is not actually
404 used here but required by gpg 1.4's implementation of this code in
405 cardglue.c. */
407 agent_scd_setattr (const char *name,
408 const unsigned char *value, size_t valuelen,
409 const char *serialno)
411 int rc;
412 char line[ASSUAN_LINELENGTH];
413 char *p;
415 (void)serialno;
417 if (!*name || !valuelen)
418 return gpg_error (GPG_ERR_INV_VALUE);
420 /* We assume that NAME does not need escaping. */
421 if (12 + strlen (name) > DIM(line)-1)
422 return gpg_error (GPG_ERR_TOO_LARGE);
424 p = stpcpy (stpcpy (line, "SCD SETATTR "), name);
425 *p++ = ' ';
426 for (; valuelen; value++, valuelen--)
428 if (p >= line + DIM(line)-5 )
429 return gpg_error (GPG_ERR_TOO_LARGE);
430 if (*value < ' ' || *value == '+' || *value == '%')
432 sprintf (p, "%%%02X", *value);
433 p += 3;
435 else if (*value == ' ')
436 *p++ = '+';
437 else
438 *p++ = *value;
440 *p = 0;
442 rc = start_agent ();
443 if (rc)
444 return rc;
446 rc = assuan_transact (agent_ctx, line, NULL, NULL,
447 default_inq_cb, NULL, NULL, NULL);
448 return rc;
453 /* Handle a CERTDATA inquiry. Note, we only send the data,
454 assuan_transact takes care of flushing and writing the END
455 command. */
456 static int
457 inq_writecert_parms (void *opaque, const char *line)
459 int rc;
460 struct writecert_parm_s *parm = opaque;
462 if (!strncmp (line, "CERTDATA", 8) && (line[8]==' '||!line[8]))
464 rc = assuan_send_data (parm->ctx, parm->certdata, parm->certdatalen);
466 else
467 rc = default_inq_cb (opaque, line);
469 return rc;
473 /* Send a WRITECERT command to the SCdaemon. */
474 int
475 agent_scd_writecert (const char *certidstr,
476 const unsigned char *certdata, size_t certdatalen)
478 int rc;
479 char line[ASSUAN_LINELENGTH];
480 struct writecert_parm_s parms;
482 rc = start_agent ();
483 if (rc)
484 return rc;
486 memset (&parms, 0, sizeof parms);
488 snprintf (line, DIM(line)-1, "SCD WRITECERT %s", certidstr);
489 line[DIM(line)-1] = 0;
490 parms.ctx = agent_ctx;
491 parms.certdata = certdata;
492 parms.certdatalen = certdatalen;
494 rc = assuan_transact (agent_ctx, line, NULL, NULL,
495 inq_writecert_parms, &parms, NULL, NULL);
497 return rc;
503 /* Handle a KEYDATA inquiry. Note, we only send the data,
504 assuan_transact takes care of flushing and writing the end */
505 static int
506 inq_writekey_parms (void *opaque, const char *line)
508 int rc;
509 struct writekey_parm_s *parm = opaque;
511 if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7]))
513 rc = assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen);
515 else
516 rc = default_inq_cb (opaque, line);
518 return rc;
522 /* Send a WRITEKEY command to the SCdaemon. */
523 int
524 agent_scd_writekey (int keyno, const char *serialno,
525 const unsigned char *keydata, size_t keydatalen)
527 int rc;
528 char line[ASSUAN_LINELENGTH];
529 struct writekey_parm_s parms;
531 (void)serialno;
533 rc = start_agent ();
534 if (rc)
535 return rc;
537 memset (&parms, 0, sizeof parms);
539 snprintf (line, DIM(line)-1, "SCD WRITEKEY --force OPENPGP.%d", keyno);
540 line[DIM(line)-1] = 0;
541 parms.ctx = agent_ctx;
542 parms.keydata = keydata;
543 parms.keydatalen = keydatalen;
545 rc = assuan_transact (agent_ctx, line, NULL, NULL,
546 inq_writekey_parms, &parms, NULL, NULL);
548 return rc;
554 /* Status callback for the SCD GENKEY command. */
555 static int
556 scd_genkey_cb (void *opaque, const char *line)
558 struct agent_card_genkey_s *parm = opaque;
559 const char *keyword = line;
560 int keywordlen;
561 gpg_error_t rc;
563 log_debug ("got status line `%s'\n", line);
564 for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
566 while (spacep (line))
567 line++;
569 if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
571 parm->fprvalid = unhexify_fpr (line, parm->fpr);
573 if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
575 gcry_mpi_t a;
576 const char *name = line;
578 while (*line && !spacep (line))
579 line++;
580 while (spacep (line))
581 line++;
583 rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, line, 0, NULL);
584 if (rc)
585 log_error ("error parsing received key data: %s\n", gpg_strerror (rc));
586 else if (*name == 'n' && spacep (name+1))
587 parm->n = a;
588 else if (*name == 'e' && spacep (name+1))
589 parm->e = a;
590 else
592 log_info ("unknown parameter name in received key data\n");
593 gcry_mpi_release (a);
596 else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
598 parm->created_at = (u32)strtoul (line, NULL, 10);
601 return 0;
604 /* Send a GENKEY command to the SCdaemon. SERIALNO is not used in
605 this implementation. If CREATEDATE has been given, it will be
606 passed to SCDAEMON so that the key can be created with this
607 timestamp; note the user needs to use the returned timestamp as old
608 versions of scddaemon don't support this option. */
610 agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
611 const char *serialno, u32 createtime)
613 int rc;
614 char line[ASSUAN_LINELENGTH];
615 gnupg_isotime_t tbuf;
617 (void)serialno;
619 rc = start_agent ();
620 if (rc)
621 return rc;
623 if (createtime)
624 epoch2isotime (tbuf, createtime);
625 else
626 *tbuf = 0;
628 memset (info, 0, sizeof *info);
629 snprintf (line, DIM(line)-1, "SCD GENKEY %s%s %s %d",
630 *tbuf? "--timestamp=":"", tbuf,
631 force? "--force":"",
632 keyno);
633 line[DIM(line)-1] = 0;
635 memset (info, 0, sizeof *info);
636 rc = assuan_transact (agent_ctx, line,
637 NULL, NULL, default_inq_cb, NULL,
638 scd_genkey_cb, info);
640 return rc;
644 static int
645 membuf_data_cb (void *opaque, const void *buffer, size_t length)
647 membuf_t *data = opaque;
649 if (buffer)
650 put_membuf (data, buffer, length);
651 return 0;
654 /* Send a sign command to the scdaemon via gpg-agent's pass thru
655 mechanism. */
657 agent_scd_pksign (const char *serialno, int hashalgo,
658 const unsigned char *indata, size_t indatalen,
659 unsigned char **r_buf, size_t *r_buflen)
661 int rc, i;
662 char *p, line[ASSUAN_LINELENGTH];
663 membuf_t data;
664 size_t len;
666 /* Note, hashalgo is not yet used but hardwired to SHA1 in SCdaemon. */
668 *r_buf = NULL;
669 *r_buflen = 0;
671 rc = start_agent ();
672 if (rc)
673 return rc;
675 if (indatalen*2 + 50 > DIM(line))
676 return gpg_error (GPG_ERR_GENERAL);
678 /* Send the serialno command to initialize the connection. We don't
679 care about the data returned. If the card has already been
680 initialized, this is a very fast command. We request the openpgp
681 card because that is waht we expect. */
682 rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
683 NULL, NULL, NULL, NULL, NULL, NULL);
684 if (rc)
685 return rc;
687 sprintf (line, "SCD SETDATA ");
688 p = line + strlen (line);
689 for (i=0; i < indatalen ; i++, p += 2 )
690 sprintf (p, "%02X", indata[i]);
691 rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
692 if (rc)
693 return rc;
695 init_membuf (&data, 1024);
696 #if 0
697 if (!hashalgo) /* Temporary test hack. */
698 snprintf (line, DIM(line)-1, "SCD PKAUTH %s", serialno);
699 else
700 #endif
701 snprintf (line, DIM(line)-1, "SCD PKSIGN %s%s",
702 hashalgo == GCRY_MD_RMD160? "--hash=rmd160 " : "",
703 serialno);
704 line[DIM(line)-1] = 0;
705 rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data,
706 default_inq_cb, NULL, NULL, NULL);
707 if (rc)
709 xfree (get_membuf (&data, &len));
710 return rc;
712 *r_buf = get_membuf (&data, r_buflen);
714 return 0;
718 /* Decrypt INDATA of length INDATALEN using the card identified by
719 SERIALNO. Return the plaintext in a nwly allocated buffer stored
720 at the address of R_BUF.
722 Note, we currently support only RSA or more exactly algorithms
723 taking one input data element. */
725 agent_scd_pkdecrypt (const char *serialno,
726 const unsigned char *indata, size_t indatalen,
727 unsigned char **r_buf, size_t *r_buflen)
729 int rc, i;
730 char *p, line[ASSUAN_LINELENGTH];
731 membuf_t data;
732 size_t len;
734 *r_buf = NULL;
735 rc = start_agent ();
736 if (rc)
737 return rc;
739 /* FIXME: use secure memory where appropriate */
740 if (indatalen*2 + 50 > DIM(line))
741 return gpg_error (GPG_ERR_GENERAL);
743 /* Send the serialno command to initialize the connection. We don't
744 care about the data returned. If the card has already been
745 initialized, this is a very fast command. We request the openpgp
746 card because that is waht we expect. */
747 rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
748 NULL, NULL, NULL, NULL, NULL, NULL);
749 if (rc)
750 return rc;
752 sprintf (line, "SCD SETDATA ");
753 p = line + strlen (line);
754 for (i=0; i < indatalen ; i++, p += 2 )
755 sprintf (p, "%02X", indata[i]);
756 rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
757 if (rc)
758 return rc;
760 init_membuf (&data, 1024);
761 snprintf (line, DIM(line)-1, "SCD PKDECRYPT %s", serialno);
762 line[DIM(line)-1] = 0;
763 rc = assuan_transact (agent_ctx, line,
764 membuf_data_cb, &data,
765 default_inq_cb, NULL, NULL, NULL);
766 if (rc)
768 xfree (get_membuf (&data, &len));
769 return rc;
771 *r_buf = get_membuf (&data, r_buflen);
772 if (!*r_buf)
773 return gpg_error (GPG_ERR_ENOMEM);
775 return 0;
779 /* Change the PIN of an OpenPGP card or reset the retry counter.
780 CHVNO 1: Change the PIN
781 2: For v1 cards: Same as 1.
782 For v2 cards: Reset the PIN using the Reset Code.
783 3: Change the admin PIN
784 101: Set a new PIN and reset the retry counter
785 102: For v1 cars: Same as 101.
786 For v2 cards: Set a new Reset Code.
787 SERIALNO is not used.
790 agent_scd_change_pin (int chvno, const char *serialno)
792 int rc;
793 char line[ASSUAN_LINELENGTH];
794 const char *reset = "";
796 (void)serialno;
798 if (chvno >= 100)
799 reset = "--reset";
800 chvno %= 100;
802 rc = start_agent ();
803 if (rc)
804 return rc;
806 snprintf (line, DIM(line)-1, "SCD PASSWD %s %d", reset, chvno);
807 line[DIM(line)-1] = 0;
808 rc = assuan_transact (agent_ctx, line, NULL, NULL,
809 default_inq_cb, NULL, NULL, NULL);
810 return rc;
814 /* Perform a CHECKPIN operation. SERIALNO should be the serial
815 number of the card - optionally followed by the fingerprint;
816 however the fingerprint is ignored here. */
818 agent_scd_checkpin (const char *serialno)
820 int rc;
821 char line[ASSUAN_LINELENGTH];
823 rc = start_agent ();
824 if (rc)
825 return rc;
827 snprintf (line, DIM(line)-1, "SCD CHECKPIN %s", serialno);
828 line[DIM(line)-1] = 0;
829 return assuan_transact (agent_ctx, line,
830 NULL, NULL,
831 default_inq_cb, NULL, NULL, NULL);
835 /* Dummy function, only used by the gpg 1.4 implementation. */
836 void
837 agent_clear_pin_cache (const char *sn)
839 (void)sn;
845 /* Note: All strings shall be UTF-8. On success the caller needs to
846 free the string stored at R_PASSPHRASE. On error NULL will be
847 stored at R_PASSPHRASE and an appropriate fpf error code
848 returned. */
849 gpg_error_t
850 agent_get_passphrase (const char *cache_id,
851 const char *err_msg,
852 const char *prompt,
853 const char *desc_msg,
854 int repeat,
855 char **r_passphrase)
857 int rc;
858 char line[ASSUAN_LINELENGTH];
859 char *arg1 = NULL;
860 char *arg2 = NULL;
861 char *arg3 = NULL;
862 char *arg4 = NULL;
863 membuf_t data;
865 *r_passphrase = NULL;
867 rc = start_agent ();
868 if (rc)
869 return rc;
871 /* Check that the gpg-agent understands the repeat option. */
872 if (assuan_transact (agent_ctx,
873 "GETINFO cmd_has_option GET_PASSPHRASE repeat",
874 NULL, NULL, NULL, NULL, NULL, NULL))
875 return gpg_error (GPG_ERR_NOT_SUPPORTED);
877 if (cache_id && *cache_id)
878 if (!(arg1 = percent_plus_escape (cache_id)))
879 goto no_mem;
880 if (err_msg && *err_msg)
881 if (!(arg2 = percent_plus_escape (err_msg)))
882 goto no_mem;
883 if (prompt && *prompt)
884 if (!(arg3 = percent_plus_escape (prompt)))
885 goto no_mem;
886 if (desc_msg && *desc_msg)
887 if (!(arg4 = percent_plus_escape (desc_msg)))
888 goto no_mem;
890 snprintf (line, DIM(line)-1,
891 "GET_PASSPHRASE --data --repeat=%d -- %s %s %s %s",
892 repeat,
893 arg1? arg1:"X",
894 arg2? arg2:"X",
895 arg3? arg3:"X",
896 arg4? arg4:"X");
897 line[DIM(line)-1] = 0;
898 xfree (arg1);
899 xfree (arg2);
900 xfree (arg3);
901 xfree (arg4);
903 init_membuf_secure (&data, 64);
904 rc = assuan_transact (agent_ctx, line,
905 membuf_data_cb, &data,
906 default_inq_cb, NULL, NULL, NULL);
908 if (rc)
909 xfree (get_membuf (&data, NULL));
910 else
912 put_membuf (&data, "", 1);
913 *r_passphrase = get_membuf (&data, NULL);
914 if (!*r_passphrase)
915 rc = gpg_error_from_syserror ();
917 return rc;
918 no_mem:
919 rc = gpg_error_from_syserror ();
920 xfree (arg1);
921 xfree (arg2);
922 xfree (arg3);
923 xfree (arg4);
924 return rc;
928 gpg_error_t
929 agent_clear_passphrase (const char *cache_id)
931 int rc;
932 char line[ASSUAN_LINELENGTH];
934 if (!cache_id || !*cache_id)
935 return 0;
937 rc = start_agent ();
938 if (rc)
939 return rc;
941 snprintf (line, DIM(line)-1, "CLEAR_PASSPHRASE %s", cache_id);
942 line[DIM(line)-1] = 0;
943 return assuan_transact (agent_ctx, line, NULL, NULL,
944 default_inq_cb, NULL, NULL, NULL);