Emit CARDCTRL status lines.
[gnupg.git] / g10 / call-agent.c
blob3ee025f96b58c194b5777b5273e6f51797d13f14
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"
42 #include "status.h"
44 #ifndef DBG_ASSUAN
45 # define DBG_ASSUAN 1
46 #endif
48 static assuan_context_t agent_ctx = NULL;
49 static int did_early_card_test;
51 struct cipher_parm_s
53 assuan_context_t ctx;
54 const char *ciphertext;
55 size_t ciphertextlen;
58 struct writecert_parm_s
60 assuan_context_t ctx;
61 const unsigned char *certdata;
62 size_t certdatalen;
65 struct writekey_parm_s
67 assuan_context_t ctx;
68 const unsigned char *keydata;
69 size_t keydatalen;
72 struct genkey_parm_s
74 assuan_context_t ctx;
75 const char *sexp;
76 size_t sexplen;
80 static int learn_status_cb (void *opaque, const char *line);
84 /* If RC is not 0, write an appropriate status message. */
85 static void
86 status_sc_op_failure (int rc)
88 switch (gpg_err_code (rc))
90 case 0:
91 break;
92 case GPG_ERR_CANCELED:
93 write_status_text (STATUS_SC_OP_FAILURE, "1");
94 break;
95 case GPG_ERR_BAD_PIN:
96 write_status_text (STATUS_SC_OP_FAILURE, "2");
97 break;
98 default:
99 write_status (STATUS_SC_OP_FAILURE);
100 break;
107 /* Try to connect to the agent via socket or fork it off and work by
108 pipes. Handle the server's initial greeting */
109 static int
110 start_agent (int for_card)
112 int rc;
114 /* Fixme: We need a context for each thread or serialize the access
115 to the agent. */
116 if (agent_ctx)
117 rc = 0;
118 else
120 rc = start_new_gpg_agent (&agent_ctx,
121 GPG_ERR_SOURCE_DEFAULT,
122 opt.homedir,
123 opt.agent_program,
124 opt.lc_ctype, opt.lc_messages,
125 opt.session_env,
126 opt.verbose, DBG_ASSUAN,
127 NULL, NULL);
128 if (!rc)
130 /* Tell the agent that we support Pinentry notifications.
131 No error checking so that it will work also with older
132 agents. */
133 assuan_transact (agent_ctx, "OPTION allow-pinentry-notify",
134 NULL, NULL, NULL, NULL, NULL, NULL);
138 if (!rc && for_card && !did_early_card_test)
140 /* Request the serial number of the card for an early test. */
141 struct agent_card_info_s info;
143 memset (&info, 0, sizeof info);
144 rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
145 NULL, NULL, NULL, NULL,
146 learn_status_cb, &info);
147 if (rc)
149 switch (gpg_err_code (rc))
151 case GPG_ERR_NOT_SUPPORTED:
152 case GPG_ERR_NO_SCDAEMON:
153 write_status_text (STATUS_CARDCTRL, "6");
154 break;
155 default:
156 write_status_text (STATUS_CARDCTRL, "4");
157 log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc));
158 break;
162 if (!rc && is_status_enabled () && info.serialno)
164 char *buf;
166 buf = xasprintf ("3 %s", info.serialno);
167 write_status_text (STATUS_CARDCTRL, buf);
168 xfree (buf);
171 agent_release_card_info (&info);
173 if (!rc)
174 did_early_card_test = 1;
178 return rc;
182 /* Return a new malloced string by unescaping the string S. Escaping
183 is percent escaping and '+'/space mapping. A binary nul will
184 silently be replaced by a 0xFF. Function returns NULL to indicate
185 an out of memory status. */
186 static char *
187 unescape_status_string (const unsigned char *s)
189 return percent_plus_unescape (s, 0xff);
193 /* Take a 20 byte hexencoded string and put it into the the provided
194 20 byte buffer FPR in binary format. */
195 static int
196 unhexify_fpr (const char *hexstr, unsigned char *fpr)
198 const char *s;
199 int n;
201 for (s=hexstr, n=0; hexdigitp (s); s++, n++)
203 if (*s || (n != 40))
204 return 0; /* no fingerprint (invalid or wrong length). */
205 for (s=hexstr, n=0; *s; s += 2, n++)
206 fpr[n] = xtoi_2 (s);
207 return 1; /* okay */
210 /* Take the serial number from LINE and return it verbatim in a newly
211 allocated string. We make sure that only hex characters are
212 returned. */
213 static char *
214 store_serialno (const char *line)
216 const char *s;
217 char *p;
219 for (s=line; hexdigitp (s); s++)
221 p = xtrymalloc (s + 1 - line);
222 if (p)
224 memcpy (p, line, s-line);
225 p[s-line] = 0;
227 return p;
232 /* This is a dummy data line callback. */
233 static int
234 dummy_data_cb (void *opaque, const void *buffer, size_t length)
236 (void)opaque;
237 (void)buffer;
238 (void)length;
239 return 0;
243 /* This is the default inquiry callback. It mainly handles the
244 Pinentry notifications. */
245 static int
246 default_inq_cb (void *opaque, const char *line)
248 (void)opaque;
250 if (!strncmp (line, "PINENTRY_LAUNCHED", 17) && (line[17]==' '||!line[17]))
252 /* There is no working server mode yet thus we use
253 AllowSetForegroundWindow window right here. We might want to
254 do this anyway in case gpg is called on the console. */
255 gnupg_allow_set_foregound_window ((pid_t)strtoul (line+17, NULL, 10));
256 /* We do not pass errors to avoid breaking other code. */
258 else
259 log_debug ("ignoring gpg-agent inquiry `%s'\n", line);
261 return 0;
266 /* Release the card info structure INFO. */
267 void
268 agent_release_card_info (struct agent_card_info_s *info)
270 if (!info)
271 return;
273 xfree (info->serialno); info->serialno = NULL;
274 xfree (info->apptype); info->apptype = NULL;
275 xfree (info->disp_name); info->disp_name = NULL;
276 xfree (info->disp_lang); info->disp_lang = NULL;
277 xfree (info->pubkey_url); info->pubkey_url = NULL;
278 xfree (info->login_data); info->login_data = NULL;
279 info->cafpr1valid = info->cafpr2valid = info->cafpr3valid = 0;
280 info->fpr1valid = info->fpr2valid = info->fpr3valid = 0;
283 static int
284 learn_status_cb (void *opaque, const char *line)
286 struct agent_card_info_s *parm = opaque;
287 const char *keyword = line;
288 int keywordlen;
289 int i;
291 for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
293 while (spacep (line))
294 line++;
296 if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
298 xfree (parm->serialno);
299 parm->serialno = store_serialno (line);
300 parm->is_v2 = (strlen (parm->serialno) >= 16
301 && xtoi_2 (parm->serialno+12) >= 2 );
303 else if (keywordlen == 7 && !memcmp (keyword, "APPTYPE", keywordlen))
305 xfree (parm->apptype);
306 parm->apptype = unescape_status_string (line);
308 else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
310 xfree (parm->disp_name);
311 parm->disp_name = unescape_status_string (line);
313 else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen))
315 xfree (parm->disp_lang);
316 parm->disp_lang = unescape_status_string (line);
318 else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen))
320 parm->disp_sex = *line == '1'? 1 : *line == '2' ? 2: 0;
322 else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
324 xfree (parm->pubkey_url);
325 parm->pubkey_url = unescape_status_string (line);
327 else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen))
329 xfree (parm->login_data);
330 parm->login_data = unescape_status_string (line);
332 else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen))
334 parm->sig_counter = strtoul (line, NULL, 0);
336 else if (keywordlen == 10 && !memcmp (keyword, "CHV-STATUS", keywordlen))
338 char *p, *buf;
340 buf = p = unescape_status_string (line);
341 if (buf)
343 while (spacep (p))
344 p++;
345 parm->chv1_cached = atoi (p);
346 while (*p && !spacep (p))
347 p++;
348 while (spacep (p))
349 p++;
350 for (i=0; *p && i < 3; i++)
352 parm->chvmaxlen[i] = atoi (p);
353 while (*p && !spacep (p))
354 p++;
355 while (spacep (p))
356 p++;
358 for (i=0; *p && i < 3; i++)
360 parm->chvretry[i] = atoi (p);
361 while (*p && !spacep (p))
362 p++;
363 while (spacep (p))
364 p++;
366 xfree (buf);
369 else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
371 int no = atoi (line);
372 while (*line && !spacep (line))
373 line++;
374 while (spacep (line))
375 line++;
376 if (no == 1)
377 parm->fpr1valid = unhexify_fpr (line, parm->fpr1);
378 else if (no == 2)
379 parm->fpr2valid = unhexify_fpr (line, parm->fpr2);
380 else if (no == 3)
381 parm->fpr3valid = unhexify_fpr (line, parm->fpr3);
383 else if (keywordlen == 6 && !memcmp (keyword, "CA-FPR", keywordlen))
385 int no = atoi (line);
386 while (*line && !spacep (line))
387 line++;
388 while (spacep (line))
389 line++;
390 if (no == 1)
391 parm->cafpr1valid = unhexify_fpr (line, parm->cafpr1);
392 else if (no == 2)
393 parm->cafpr2valid = unhexify_fpr (line, parm->cafpr2);
394 else if (no == 3)
395 parm->cafpr3valid = unhexify_fpr (line, parm->cafpr3);
397 else if (keywordlen == 8 && !memcmp (keyword, "KEY-ATTR", keywordlen))
399 int keyno, algo, nbits;
401 sscanf (line, "%d %d %d", &keyno, &algo, &nbits);
402 keyno--;
403 if (keyno >= 0 && keyno < DIM (parm->key_attr))
405 parm->key_attr[keyno].algo = algo;
406 parm->key_attr[keyno].nbits = nbits;
410 return 0;
413 /* Call the agent to learn about a smartcard */
415 agent_learn (struct agent_card_info_s *info)
417 int rc;
419 rc = start_agent (1);
420 if (rc)
421 return rc;
423 memset (info, 0, sizeof *info);
424 rc = assuan_transact (agent_ctx, "SCD LEARN --force",
425 dummy_data_cb, NULL, default_inq_cb, NULL,
426 learn_status_cb, info);
427 /* Also try to get the key attributes. */
428 if (!rc)
429 agent_scd_getattr ("KEY-ATTR", info);
431 return rc;
434 /* Call the agent to retrieve a data object. This function returns
435 the data in the same structure as used by the learn command. It is
436 allowed to update such a structure using this commmand. */
438 agent_scd_getattr (const char *name, struct agent_card_info_s *info)
440 int rc;
441 char line[ASSUAN_LINELENGTH];
443 if (!*name)
444 return gpg_error (GPG_ERR_INV_VALUE);
446 /* We assume that NAME does not need escaping. */
447 if (12 + strlen (name) > DIM(line)-1)
448 return gpg_error (GPG_ERR_TOO_LARGE);
449 stpcpy (stpcpy (line, "SCD GETATTR "), name);
451 rc = start_agent (1);
452 if (rc)
453 return rc;
455 rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, NULL,
456 learn_status_cb, info);
458 return rc;
462 /* Send an setattr command to the SCdaemon. SERIALNO is not actually
463 used here but required by gpg 1.4's implementation of this code in
464 cardglue.c. */
466 agent_scd_setattr (const char *name,
467 const unsigned char *value, size_t valuelen,
468 const char *serialno)
470 int rc;
471 char line[ASSUAN_LINELENGTH];
472 char *p;
474 (void)serialno;
476 if (!*name || !valuelen)
477 return gpg_error (GPG_ERR_INV_VALUE);
479 /* We assume that NAME does not need escaping. */
480 if (12 + strlen (name) > DIM(line)-1)
481 return gpg_error (GPG_ERR_TOO_LARGE);
483 p = stpcpy (stpcpy (line, "SCD SETATTR "), name);
484 *p++ = ' ';
485 for (; valuelen; value++, valuelen--)
487 if (p >= line + DIM(line)-5 )
488 return gpg_error (GPG_ERR_TOO_LARGE);
489 if (*value < ' ' || *value == '+' || *value == '%')
491 sprintf (p, "%%%02X", *value);
492 p += 3;
494 else if (*value == ' ')
495 *p++ = '+';
496 else
497 *p++ = *value;
499 *p = 0;
501 rc = start_agent (1);
502 if (!rc)
504 rc = assuan_transact (agent_ctx, line, NULL, NULL,
505 default_inq_cb, NULL, NULL, NULL);
508 status_sc_op_failure (rc);
509 return rc;
514 /* Handle a CERTDATA inquiry. Note, we only send the data,
515 assuan_transact takes care of flushing and writing the END
516 command. */
517 static int
518 inq_writecert_parms (void *opaque, const char *line)
520 int rc;
521 struct writecert_parm_s *parm = opaque;
523 if (!strncmp (line, "CERTDATA", 8) && (line[8]==' '||!line[8]))
525 rc = assuan_send_data (parm->ctx, parm->certdata, parm->certdatalen);
527 else
528 rc = default_inq_cb (opaque, line);
530 return rc;
534 /* Send a WRITECERT command to the SCdaemon. */
535 int
536 agent_scd_writecert (const char *certidstr,
537 const unsigned char *certdata, size_t certdatalen)
539 int rc;
540 char line[ASSUAN_LINELENGTH];
541 struct writecert_parm_s parms;
543 rc = start_agent (1);
544 if (rc)
545 return rc;
547 memset (&parms, 0, sizeof parms);
549 snprintf (line, DIM(line)-1, "SCD WRITECERT %s", certidstr);
550 line[DIM(line)-1] = 0;
551 parms.ctx = agent_ctx;
552 parms.certdata = certdata;
553 parms.certdatalen = certdatalen;
555 rc = assuan_transact (agent_ctx, line, NULL, NULL,
556 inq_writecert_parms, &parms, NULL, NULL);
558 return rc;
563 /* Handle a KEYDATA inquiry. Note, we only send the data,
564 assuan_transact takes care of flushing and writing the end */
565 static int
566 inq_writekey_parms (void *opaque, const char *line)
568 int rc;
569 struct writekey_parm_s *parm = opaque;
571 if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7]))
573 rc = assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen);
575 else
576 rc = default_inq_cb (opaque, line);
578 return rc;
582 /* Send a WRITEKEY command to the SCdaemon. */
583 int
584 agent_scd_writekey (int keyno, const char *serialno,
585 const unsigned char *keydata, size_t keydatalen)
587 int rc;
588 char line[ASSUAN_LINELENGTH];
589 struct writekey_parm_s parms;
591 (void)serialno;
593 rc = start_agent (1);
594 if (rc)
595 return rc;
597 memset (&parms, 0, sizeof parms);
599 snprintf (line, DIM(line)-1, "SCD WRITEKEY --force OPENPGP.%d", keyno);
600 line[DIM(line)-1] = 0;
601 parms.ctx = agent_ctx;
602 parms.keydata = keydata;
603 parms.keydatalen = keydatalen;
605 rc = assuan_transact (agent_ctx, line, NULL, NULL,
606 inq_writekey_parms, &parms, NULL, NULL);
608 status_sc_op_failure (rc);
609 return rc;
614 /* Status callback for the SCD GENKEY command. */
615 static int
616 scd_genkey_cb (void *opaque, const char *line)
618 struct agent_card_genkey_s *parm = opaque;
619 const char *keyword = line;
620 int keywordlen;
621 gpg_error_t rc;
623 for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
625 while (spacep (line))
626 line++;
628 if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
630 parm->fprvalid = unhexify_fpr (line, parm->fpr);
632 if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
634 gcry_mpi_t a;
635 const char *name = line;
637 while (*line && !spacep (line))
638 line++;
639 while (spacep (line))
640 line++;
642 rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, line, 0, NULL);
643 if (rc)
644 log_error ("error parsing received key data: %s\n", gpg_strerror (rc));
645 else if (*name == 'n' && spacep (name+1))
646 parm->n = a;
647 else if (*name == 'e' && spacep (name+1))
648 parm->e = a;
649 else
651 log_info ("unknown parameter name in received key data\n");
652 gcry_mpi_release (a);
655 else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
657 parm->created_at = (u32)strtoul (line, NULL, 10);
660 return 0;
663 /* Send a GENKEY command to the SCdaemon. SERIALNO is not used in
664 this implementation. If CREATEDATE has been given, it will be
665 passed to SCDAEMON so that the key can be created with this
666 timestamp; note the user needs to use the returned timestamp as old
667 versions of scddaemon don't support this option. */
669 agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
670 const char *serialno, u32 createtime)
672 int rc;
673 char line[ASSUAN_LINELENGTH];
674 gnupg_isotime_t tbuf;
676 (void)serialno;
678 rc = start_agent (1);
679 if (rc)
680 return rc;
682 if (createtime)
683 epoch2isotime (tbuf, createtime);
684 else
685 *tbuf = 0;
687 memset (info, 0, sizeof *info);
688 snprintf (line, DIM(line)-1, "SCD GENKEY %s%s %s %d",
689 *tbuf? "--timestamp=":"", tbuf,
690 force? "--force":"",
691 keyno);
692 line[DIM(line)-1] = 0;
694 memset (info, 0, sizeof *info);
695 rc = assuan_transact (agent_ctx, line,
696 NULL, NULL, default_inq_cb, NULL,
697 scd_genkey_cb, info);
699 status_sc_op_failure (rc);
700 return rc;
704 static int
705 membuf_data_cb (void *opaque, const void *buffer, size_t length)
707 membuf_t *data = opaque;
709 if (buffer)
710 put_membuf (data, buffer, length);
711 return 0;
714 /* Send a sign command to the scdaemon via gpg-agent's pass thru
715 mechanism. */
717 agent_scd_pksign (const char *serialno, int hashalgo,
718 const unsigned char *indata, size_t indatalen,
719 unsigned char **r_buf, size_t *r_buflen)
721 int rc, i;
722 char *p, line[ASSUAN_LINELENGTH];
723 membuf_t data;
724 size_t len;
726 /* Note, hashalgo is not yet used but hardwired to SHA1 in SCdaemon. */
728 *r_buf = NULL;
729 *r_buflen = 0;
731 rc = start_agent (1);
732 if (rc)
733 return rc;
735 if (indatalen*2 + 50 > DIM(line))
736 return gpg_error (GPG_ERR_GENERAL);
738 /* Send the serialno command to initialize the connection. We don't
739 care about the data returned. If the card has already been
740 initialized, this is a very fast command. We request the openpgp
741 card because that is what we expect. */
742 rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
743 NULL, NULL, NULL, NULL, NULL, NULL);
744 if (rc)
745 return rc;
747 sprintf (line, "SCD SETDATA ");
748 p = line + strlen (line);
749 for (i=0; i < indatalen ; i++, p += 2 )
750 sprintf (p, "%02X", indata[i]);
751 rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
752 if (rc)
753 return rc;
755 init_membuf (&data, 1024);
756 #if 0
757 if (!hashalgo) /* Temporary test hack. */
758 snprintf (line, DIM(line)-1, "SCD PKAUTH %s", serialno);
759 else
760 #endif
761 snprintf (line, DIM(line)-1, "SCD PKSIGN %s%s",
762 hashalgo == GCRY_MD_RMD160? "--hash=rmd160 " : "",
763 serialno);
764 line[DIM(line)-1] = 0;
765 rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data,
766 default_inq_cb, NULL, NULL, NULL);
767 if (rc)
769 xfree (get_membuf (&data, &len));
771 else
772 *r_buf = get_membuf (&data, r_buflen);
774 status_sc_op_failure (rc);
775 return rc;
779 /* Decrypt INDATA of length INDATALEN using the card identified by
780 SERIALNO. Return the plaintext in a nwly allocated buffer stored
781 at the address of R_BUF.
783 Note, we currently support only RSA or more exactly algorithms
784 taking one input data element. */
786 agent_scd_pkdecrypt (const char *serialno,
787 const unsigned char *indata, size_t indatalen,
788 unsigned char **r_buf, size_t *r_buflen)
790 int rc, i;
791 char *p, line[ASSUAN_LINELENGTH];
792 membuf_t data;
793 size_t len;
795 *r_buf = NULL;
796 rc = start_agent (1);
797 if (rc)
798 return rc;
800 /* FIXME: use secure memory where appropriate */
801 if (indatalen*2 + 50 > DIM(line))
802 return gpg_error (GPG_ERR_GENERAL);
804 /* Send the serialno command to initialize the connection. We don't
805 care about the data returned. If the card has already been
806 initialized, this is a very fast command. We request the openpgp
807 card because that is what we expect. */
808 rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
809 NULL, NULL, NULL, NULL, NULL, NULL);
810 if (rc)
811 return rc;
813 sprintf (line, "SCD SETDATA ");
814 p = line + strlen (line);
815 for (i=0; i < indatalen ; i++, p += 2 )
816 sprintf (p, "%02X", indata[i]);
817 rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
818 if (rc)
819 return rc;
821 init_membuf (&data, 1024);
822 snprintf (line, DIM(line)-1, "SCD PKDECRYPT %s", serialno);
823 line[DIM(line)-1] = 0;
824 rc = assuan_transact (agent_ctx, line,
825 membuf_data_cb, &data,
826 default_inq_cb, NULL, NULL, NULL);
827 if (rc)
829 xfree (get_membuf (&data, &len));
831 else
833 *r_buf = get_membuf (&data, r_buflen);
834 if (!*r_buf)
835 rc = gpg_error (GPG_ERR_ENOMEM);
838 status_sc_op_failure (rc);
839 return rc;
844 /* Send a READCERT command to the SCdaemon. */
845 int
846 agent_scd_readcert (const char *certidstr,
847 void **r_buf, size_t *r_buflen)
849 int rc;
850 char line[ASSUAN_LINELENGTH];
851 membuf_t data;
852 size_t len;
854 *r_buf = NULL;
855 rc = start_agent (1);
856 if (rc)
857 return rc;
859 init_membuf (&data, 2048);
861 snprintf (line, DIM(line)-1, "SCD READCERT %s", certidstr);
862 line[DIM(line)-1] = 0;
863 rc = assuan_transact (agent_ctx, line,
864 membuf_data_cb, &data,
865 default_inq_cb, NULL, NULL, NULL);
866 if (rc)
868 xfree (get_membuf (&data, &len));
869 return rc;
871 *r_buf = get_membuf (&data, r_buflen);
872 if (!*r_buf)
873 return gpg_error (GPG_ERR_ENOMEM);
875 return 0;
880 /* Change the PIN of an OpenPGP card or reset the retry counter.
881 CHVNO 1: Change the PIN
882 2: For v1 cards: Same as 1.
883 For v2 cards: Reset the PIN using the Reset Code.
884 3: Change the admin PIN
885 101: Set a new PIN and reset the retry counter
886 102: For v1 cars: Same as 101.
887 For v2 cards: Set a new Reset Code.
888 SERIALNO is not used.
891 agent_scd_change_pin (int chvno, const char *serialno)
893 int rc;
894 char line[ASSUAN_LINELENGTH];
895 const char *reset = "";
897 (void)serialno;
899 if (chvno >= 100)
900 reset = "--reset";
901 chvno %= 100;
903 rc = start_agent (1);
904 if (rc)
905 return rc;
907 snprintf (line, DIM(line)-1, "SCD PASSWD %s %d", reset, chvno);
908 line[DIM(line)-1] = 0;
909 rc = assuan_transact (agent_ctx, line, NULL, NULL,
910 default_inq_cb, NULL, NULL, NULL);
911 status_sc_op_failure (rc);
912 return rc;
916 /* Perform a CHECKPIN operation. SERIALNO should be the serial
917 number of the card - optionally followed by the fingerprint;
918 however the fingerprint is ignored here. */
920 agent_scd_checkpin (const char *serialno)
922 int rc;
923 char line[ASSUAN_LINELENGTH];
925 rc = start_agent (1);
926 if (rc)
927 return rc;
929 snprintf (line, DIM(line)-1, "SCD CHECKPIN %s", serialno);
930 line[DIM(line)-1] = 0;
931 rc = assuan_transact (agent_ctx, line,
932 NULL, NULL,
933 default_inq_cb, NULL, NULL, NULL);
934 status_sc_op_failure (rc);
935 return rc;
939 /* Dummy function, only used by the gpg 1.4 implementation. */
940 void
941 agent_clear_pin_cache (const char *sn)
943 (void)sn;
949 /* Note: All strings shall be UTF-8. On success the caller needs to
950 free the string stored at R_PASSPHRASE. On error NULL will be
951 stored at R_PASSPHRASE and an appropriate fpf error code
952 returned. */
953 gpg_error_t
954 agent_get_passphrase (const char *cache_id,
955 const char *err_msg,
956 const char *prompt,
957 const char *desc_msg,
958 int repeat,
959 int check,
960 char **r_passphrase)
962 int rc;
963 char line[ASSUAN_LINELENGTH];
964 char *arg1 = NULL;
965 char *arg2 = NULL;
966 char *arg3 = NULL;
967 char *arg4 = NULL;
968 membuf_t data;
970 *r_passphrase = NULL;
972 rc = start_agent (0);
973 if (rc)
974 return rc;
976 /* Check that the gpg-agent understands the repeat option. */
977 if (assuan_transact (agent_ctx,
978 "GETINFO cmd_has_option GET_PASSPHRASE repeat",
979 NULL, NULL, NULL, NULL, NULL, NULL))
980 return gpg_error (GPG_ERR_NOT_SUPPORTED);
982 if (cache_id && *cache_id)
983 if (!(arg1 = percent_plus_escape (cache_id)))
984 goto no_mem;
985 if (err_msg && *err_msg)
986 if (!(arg2 = percent_plus_escape (err_msg)))
987 goto no_mem;
988 if (prompt && *prompt)
989 if (!(arg3 = percent_plus_escape (prompt)))
990 goto no_mem;
991 if (desc_msg && *desc_msg)
992 if (!(arg4 = percent_plus_escape (desc_msg)))
993 goto no_mem;
995 snprintf (line, DIM(line)-1,
996 "GET_PASSPHRASE --data --repeat=%d%s -- %s %s %s %s",
997 repeat,
998 check? " --check --qualitybar":"",
999 arg1? arg1:"X",
1000 arg2? arg2:"X",
1001 arg3? arg3:"X",
1002 arg4? arg4:"X");
1003 line[DIM(line)-1] = 0;
1004 xfree (arg1);
1005 xfree (arg2);
1006 xfree (arg3);
1007 xfree (arg4);
1009 init_membuf_secure (&data, 64);
1010 rc = assuan_transact (agent_ctx, line,
1011 membuf_data_cb, &data,
1012 default_inq_cb, NULL, NULL, NULL);
1014 if (rc)
1015 xfree (get_membuf (&data, NULL));
1016 else
1018 put_membuf (&data, "", 1);
1019 *r_passphrase = get_membuf (&data, NULL);
1020 if (!*r_passphrase)
1021 rc = gpg_error_from_syserror ();
1023 return rc;
1024 no_mem:
1025 rc = gpg_error_from_syserror ();
1026 xfree (arg1);
1027 xfree (arg2);
1028 xfree (arg3);
1029 xfree (arg4);
1030 return rc;
1034 gpg_error_t
1035 agent_clear_passphrase (const char *cache_id)
1037 int rc;
1038 char line[ASSUAN_LINELENGTH];
1040 if (!cache_id || !*cache_id)
1041 return 0;
1043 rc = start_agent (0);
1044 if (rc)
1045 return rc;
1047 snprintf (line, DIM(line)-1, "CLEAR_PASSPHRASE %s", cache_id);
1048 line[DIM(line)-1] = 0;
1049 return assuan_transact (agent_ctx, line, NULL, NULL,
1050 default_inq_cb, NULL, NULL, NULL);