444048a47fbad995df2c96e2bd998654a7cbfae5
[gnupg.git] / g10 / call-agent.c
1 /* call-agent.c - Divert GPG operations to the agent.
2  * Copyright (C) 2001, 2002, 2003, 2006, 2007, 
3  *               2008 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
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.
11  *
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.
16  *
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/>.
19  */
20
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>
33
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
43 #ifndef DBG_ASSUAN
44 # define DBG_ASSUAN 1
45 #endif
46
47 static assuan_context_t agent_ctx = NULL;
48
49 struct cipher_parm_s 
50 {
51   assuan_context_t ctx;
52   const char *ciphertext;
53   size_t ciphertextlen;
54 };
55
56 struct writecert_parm_s
57 {
58   assuan_context_t ctx;
59   const unsigned char *certdata;
60   size_t certdatalen;
61 };
62
63 struct writekey_parm_s
64 {
65   assuan_context_t ctx;
66   const unsigned char *keydata;
67   size_t keydatalen;
68 };
69
70 struct genkey_parm_s 
71 {
72   assuan_context_t ctx;
73   const char *sexp;
74   size_t sexplen;
75 };
76
77
78 \f
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)
83 {
84   int rc;
85
86   if (agent_ctx)
87     return 0; /* Fixme: We need a context for each thread or serialize
88                  the access to the agent. */
89
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)
100     {
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);
106     }
107
108   return rc;
109 }
110
111
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)
118 {
119   return percent_plus_unescape (s, 0xff);
120 }
121
122
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)
127 {
128   const char *s;
129   int n;
130
131   for (s=hexstr, n=0; hexdigitp (s); s++, n++)
132     ;
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 */
139 }
140
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)
146 {
147   const char *s;
148   char *p;
149
150   for (s=line; hexdigitp (s); s++)
151     ;
152   p = xtrymalloc (s + 1 - line);
153   if (p)
154     {
155       memcpy (p, line, s-line);
156       p[s-line] = 0;
157     }
158   return p;
159 }
160
161
162 \f
163 /* This is a dummy data line callback.  */
164 static int
165 dummy_data_cb (void *opaque, const void *buffer, size_t length)
166 {
167   (void)opaque;
168   (void)buffer;
169   (void)length;
170   return 0;
171 }
172
173
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)
178 {
179   (void)opaque;
180
181   if (!strncmp (line, "PINENTRY_LAUNCHED", 17) && (line[17]==' '||!line[17]))
182     {
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.  */
188     }
189   else
190     log_debug ("ignoring gpg-agent inquiry `%s'\n", line);
191
192   return 0;
193 }
194
195
196
197 /* Release the card info structure INFO. */
198 void
199 agent_release_card_info (struct agent_card_info_s *info)
200 {
201   if (!info)
202     return;
203
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;
212 }
213
214 static int
215 learn_status_cb (void *opaque, const char *line)
216 {
217   struct agent_card_info_s *parm = opaque;
218   const char *keyword = line;
219   int keywordlen;
220   int i;
221
222   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
223     ;
224   while (spacep (line))
225     line++;
226
227   if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
228     {
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 );
233     }
234   else if (keywordlen == 7 && !memcmp (keyword, "APPTYPE", keywordlen))
235     {
236       xfree (parm->apptype);
237       parm->apptype = unescape_status_string (line);
238     }
239   else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
240     {
241       xfree (parm->disp_name);
242       parm->disp_name = unescape_status_string (line);
243     }
244   else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen))
245     {
246       xfree (parm->disp_lang);
247       parm->disp_lang = unescape_status_string (line);
248     }
249   else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen))
250     {
251       parm->disp_sex = *line == '1'? 1 : *line == '2' ? 2: 0;
252     }
253   else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
254     {
255       xfree (parm->pubkey_url);
256       parm->pubkey_url = unescape_status_string (line);
257     }
258   else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen))
259     {
260       xfree (parm->login_data);
261       parm->login_data = unescape_status_string (line);
262     }
263   else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen))
264     {
265       parm->sig_counter = strtoul (line, NULL, 0);
266     }
267   else if (keywordlen == 10 && !memcmp (keyword, "CHV-STATUS", keywordlen))
268     {
269       char *p, *buf;
270
271       buf = p = unescape_status_string (line);
272       if (buf)
273         {
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++)
282             {
283               parm->chvmaxlen[i] = atoi (p);
284               while (*p && !spacep (p))
285                 p++;
286               while (spacep (p))
287                 p++;
288             }
289           for (i=0; *p && i < 3; i++)
290             {
291               parm->chvretry[i] = atoi (p);
292               while (*p && !spacep (p))
293                 p++;
294               while (spacep (p))
295                 p++;
296             }
297           xfree (buf);
298         }
299     }
300   else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
301     {
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);
313     }
314   else if (keywordlen == 6 && !memcmp (keyword, "CA-FPR", keywordlen))
315     {
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);
327     }
328   
329   return 0;
330 }
331
332 /* Call the agent to learn about a smartcard */
333 int
334 agent_learn (struct agent_card_info_s *info)
335 {
336   int rc;
337
338   rc = start_agent ();
339   if (rc)
340     return rc;
341
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);
346   
347   return rc;
348 }
349
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. */
353 int
354 agent_scd_getattr (const char *name, struct agent_card_info_s *info)
355 {
356   int rc;
357   char line[ASSUAN_LINELENGTH];
358
359   if (!*name)
360     return gpg_error (GPG_ERR_INV_VALUE);
361
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); 
366
367   rc = start_agent ();
368   if (rc)
369     return rc;
370
371   rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, NULL,
372                         learn_status_cb, info);
373   
374   return rc;
375 }
376
377 \f
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. */
381 int
382 agent_scd_setattr (const char *name,
383                    const unsigned char *value, size_t valuelen,
384                    const char *serialno)
385 {
386   int rc;
387   char line[ASSUAN_LINELENGTH];
388   char *p;
389
390   (void)serialno;
391
392   if (!*name || !valuelen)
393     return gpg_error (GPG_ERR_INV_VALUE);
394
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);
398       
399   p = stpcpy (stpcpy (line, "SCD SETATTR "), name); 
400   *p++ = ' ';
401   for (; valuelen; value++, valuelen--)
402     {
403       if (p >= line + DIM(line)-5 )
404         return gpg_error (GPG_ERR_TOO_LARGE);
405       if (*value < ' ' || *value == '+' || *value == '%')
406         {
407           sprintf (p, "%%%02X", *value);
408           p += 3;
409         }
410       else if (*value == ' ')
411         *p++ = '+';
412       else
413         *p++ = *value;
414     }
415   *p = 0;
416
417   rc = start_agent ();
418   if (rc)
419     return rc;
420
421   rc = assuan_transact (agent_ctx, line, NULL, NULL, 
422                         default_inq_cb, NULL, NULL, NULL);
423   return rc;
424 }
425
426
427 \f
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)
433 {
434   int rc;
435   struct writecert_parm_s *parm = opaque; 
436
437   if (!strncmp (line, "CERTDATA", 8) && (line[8]==' '||!line[8]))
438     {
439       rc = assuan_send_data (parm->ctx, parm->certdata, parm->certdatalen);
440     }
441   else
442     rc = default_inq_cb (opaque, line);
443
444   return rc;
445 }
446
447
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)
452 {
453   int rc;
454   char line[ASSUAN_LINELENGTH];
455   struct writecert_parm_s parms;
456
457   rc = start_agent ();
458   if (rc)
459     return rc;
460
461   memset (&parms, 0, sizeof parms);
462
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;
468   
469   rc = assuan_transact (agent_ctx, line, NULL, NULL,
470                         inq_writecert_parms, &parms, NULL, NULL);
471
472   return rc;
473 }
474
475
476
477 \f
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)
482 {
483   int rc;
484   struct writekey_parm_s *parm = opaque; 
485
486   if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7]))
487     {
488       rc = assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen);
489     }
490   else
491     rc = default_inq_cb (opaque, line);
492
493   return rc;
494 }
495
496
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)
501 {
502   int rc;
503   char line[ASSUAN_LINELENGTH];
504   struct writekey_parm_s parms;
505
506   (void)serialno;
507
508   rc = start_agent ();
509   if (rc)
510     return rc;
511
512   memset (&parms, 0, sizeof parms);
513
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;
519   
520   rc = assuan_transact (agent_ctx, line, NULL, NULL,
521                         inq_writekey_parms, &parms, NULL, NULL);
522
523   return rc;
524 }
525
526
527
528 \f
529 /* Status callback for the SCD GENKEY command. */
530 static int
531 scd_genkey_cb (void *opaque, const char *line)
532 {
533   struct agent_card_genkey_s *parm = opaque;
534   const char *keyword = line;
535   int keywordlen;
536   gpg_error_t rc;
537
538   log_debug ("got status line `%s'\n", line);
539   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
540     ;
541   while (spacep (line))
542     line++;
543
544   if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
545     {
546       parm->fprvalid = unhexify_fpr (line, parm->fpr);
547     }
548   if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
549     {
550       gcry_mpi_t a;
551       const char *name = line;
552
553       while (*line && !spacep (line))
554         line++;
555       while (spacep (line))
556         line++;
557
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
566         {
567           log_info ("unknown parameter name in received key data\n");
568           gcry_mpi_release (a);
569         }
570     }
571   else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
572     {
573       parm->created_at = (u32)strtoul (line, NULL, 10);
574     }
575
576   return 0;
577 }
578
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.  */
584 int
585 agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
586                   const char *serialno, u32 createtime)
587 {
588   int rc;
589   char line[ASSUAN_LINELENGTH];
590   gnupg_isotime_t tbuf;
591
592   (void)serialno;
593
594   rc = start_agent ();
595   if (rc)
596     return rc;
597
598   if (createtime)
599     epoch2isotime (tbuf, createtime);
600   else
601     *tbuf = 0;
602
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;
609
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);
614   
615   return rc;
616 }
617
618 \f
619 static int
620 membuf_data_cb (void *opaque, const void *buffer, size_t length)
621 {
622   membuf_t *data = opaque;
623
624   if (buffer)
625     put_membuf (data, buffer, length);
626   return 0;
627 }
628   
629 /* Send a sign command to the scdaemon via gpg-agent's pass thru
630    mechanism. */
631 int
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)
635 {
636   int rc, i;
637   char *p, line[ASSUAN_LINELENGTH];
638   membuf_t data;
639   size_t len;
640
641   /* Note, hashalgo is not yet used but hardwired to SHA1 in SCdaemon. */
642
643   *r_buf = NULL;
644   *r_buflen = 0;
645
646   rc = start_agent ();
647   if (rc)
648     return rc;
649
650   if (indatalen*2 + 50 > DIM(line))
651     return gpg_error (GPG_ERR_GENERAL);
652
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;
661
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;
669
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)
683     {
684       xfree (get_membuf (&data, &len));
685       return rc;
686     }
687   *r_buf = get_membuf (&data, r_buflen);
688
689   return 0;
690 }
691
692
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. 
696
697    Note, we currently support only RSA or more exactly algorithms
698    taking one input data element. */
699 int
700 agent_scd_pkdecrypt (const char *serialno,
701                      const unsigned char *indata, size_t indatalen,
702                      unsigned char **r_buf, size_t *r_buflen)
703 {
704   int rc, i;
705   char *p, line[ASSUAN_LINELENGTH];
706   membuf_t data;
707   size_t len;
708
709   *r_buf = NULL;
710   rc = start_agent ();
711   if (rc)
712     return rc;
713
714   /* FIXME: use secure memory where appropriate */
715   if (indatalen*2 + 50 > DIM(line))
716     return gpg_error (GPG_ERR_GENERAL);
717
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;
726
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;
734
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)
742     {
743       xfree (get_membuf (&data, &len));
744       return rc;
745     }
746   *r_buf = get_membuf (&data, r_buflen);
747   if (!*r_buf)
748     return gpg_error (GPG_ERR_ENOMEM);
749
750   return 0;
751 }
752
753
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.
763  */
764 int
765 agent_scd_change_pin (int chvno, const char *serialno)
766 {
767   int rc;
768   char line[ASSUAN_LINELENGTH];
769   const char *reset = "";
770
771   (void)serialno;
772
773   if (chvno >= 100)
774     reset = "--reset";
775   chvno %= 100;
776
777   rc = start_agent ();
778   if (rc)
779     return rc;
780
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;
786 }
787
788
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. */
792 int
793 agent_scd_checkpin  (const char *serialno)
794 {
795   int rc;
796   char line[ASSUAN_LINELENGTH];
797
798   rc = start_agent ();
799   if (rc)
800     return rc;
801
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);
807 }
808
809
810 /* Dummy function, only used by the gpg 1.4 implementation. */
811 void
812 agent_clear_pin_cache (const char *sn)
813 {
814   (void)sn;
815 }
816
817
818
819 \f
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)
831 {
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;
839
840   *r_passphrase = NULL;
841
842   rc = start_agent ();
843   if (rc)
844     return rc;
845
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);
851
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;
864
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);
877
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);
882
883   if (rc)
884     xfree (get_membuf (&data, NULL));
885   else 
886     {
887       put_membuf (&data, "", 1);
888       *r_passphrase = get_membuf (&data, NULL);
889       if (!*r_passphrase)
890         rc = gpg_error_from_syserror ();
891     }
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;
900 }
901
902
903 gpg_error_t
904 agent_clear_passphrase (const char *cache_id)
905 {
906   int rc;
907   char line[ASSUAN_LINELENGTH];
908
909   if (!cache_id || !*cache_id)
910     return 0;
911
912   rc = start_agent ();
913   if (rc)
914     return rc;
915
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);
920 }