Finished support for v2 cards with the exception of secure messaging.
[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   char *buffer, *d;
120
121   buffer = d = xtrymalloc (strlen (s)+1);
122   if (!buffer)
123     return NULL;
124   while (*s)
125     {
126       if (*s == '%' && s[1] && s[2])
127         { 
128           s++;
129           *d = xtoi_2 (s);
130           if (!*d)
131             *d = '\xff';
132           d++;
133           s += 2;
134         }
135       else if (*s == '+')
136         {
137           *d++ = ' ';
138           s++;
139         }
140       else
141         *d++ = *s++;
142     }
143   *d = 0; 
144   return buffer;
145 }
146
147 /* Copy the text ATEXT into the buffer P and do plus '+' and percent
148    escaping.  Note that the provided buffer needs to be 3 times the
149    size of ATEXT plus 1.  Returns a pointer to the leading Nul in P. */
150 static char *
151 percent_plus_escape (char *p, const char *atext)
152 {
153   const unsigned char *s;
154
155   for (s=atext; *s; s++)
156     {
157       if (*s < ' ' || *s == '+')
158         {
159           sprintf (p, "%%%02X", *s);
160           p += 3;
161         }
162       else if (*s == ' ')
163         *p++ = '+';
164       else
165         *p++ = *s;
166     }
167   *p = 0;
168   return p;
169 }
170
171 /* Take a 20 byte hexencoded string and put it into the the provided
172    20 byte buffer FPR in binary format. */
173 static int
174 unhexify_fpr (const char *hexstr, unsigned char *fpr)
175 {
176   const char *s;
177   int n;
178
179   for (s=hexstr, n=0; hexdigitp (s); s++, n++)
180     ;
181   if (*s || (n != 40))
182     return 0; /* no fingerprint (invalid or wrong length). */
183   n /= 2;
184   for (s=hexstr, n=0; *s; s += 2, n++)
185     fpr[n] = xtoi_2 (s);
186   return 1; /* okay */
187 }
188
189 /* Take the serial number from LINE and return it verbatim in a newly
190    allocated string.  We make sure that only hex characters are
191    returned. */
192 static char *
193 store_serialno (const char *line)
194 {
195   const char *s;
196   char *p;
197
198   for (s=line; hexdigitp (s); s++)
199     ;
200   p = xtrymalloc (s + 1 - line);
201   if (p)
202     {
203       memcpy (p, line, s-line);
204       p[s-line] = 0;
205     }
206   return p;
207 }
208
209
210 \f
211 /* This is the default inquiry callback.  It mainly handles the
212    Pinentry notifications.  */
213 static int
214 default_inq_cb (void *opaque, const char *line)
215 {
216   (void)opaque;
217
218   if (!strncmp (line, "PINENTRY_LAUNCHED", 17) && (line[17]==' '||!line[17]))
219     {
220       /* There is no working server mode yet thus we use
221          AllowSetForegroundWindow window right here.  We might want to
222          do this anyway in case gpg is called on the console. */
223       gnupg_allow_set_foregound_window ((pid_t)strtoul (line+17, NULL, 10));
224       /* We do not pass errors to avoid breaking other code.  */
225     }
226   else
227     log_debug ("ignoring gpg-agent inquiry `%s'\n", line);
228
229   return 0;
230 }
231
232
233
234 /* Release the card info structure INFO. */
235 void
236 agent_release_card_info (struct agent_card_info_s *info)
237 {
238   if (!info)
239     return;
240
241   xfree (info->serialno); info->serialno = NULL;
242   xfree (info->disp_name); info->disp_name = NULL;
243   xfree (info->disp_lang); info->disp_lang = NULL;
244   xfree (info->pubkey_url); info->pubkey_url = NULL;
245   xfree (info->login_data); info->login_data = NULL;
246   info->cafpr1valid = info->cafpr2valid = info->cafpr3valid = 0;
247   info->fpr1valid = info->fpr2valid = info->fpr3valid = 0;
248 }
249
250 static int
251 learn_status_cb (void *opaque, const char *line)
252 {
253   struct agent_card_info_s *parm = opaque;
254   const char *keyword = line;
255   int keywordlen;
256   int i;
257
258   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
259     ;
260   while (spacep (line))
261     line++;
262
263   if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
264     {
265       xfree (parm->serialno);
266       parm->serialno = store_serialno (line);
267       parm->is_v2 = (strlen (parm->serialno) >= 16 
268                      && xtoi_2 (parm->serialno+12) >= 2 );
269     }
270   else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
271     {
272       xfree (parm->disp_name);
273       parm->disp_name = unescape_status_string (line);
274     }
275   else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen))
276     {
277       xfree (parm->disp_lang);
278       parm->disp_lang = unescape_status_string (line);
279     }
280   else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen))
281     {
282       parm->disp_sex = *line == '1'? 1 : *line == '2' ? 2: 0;
283     }
284   else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
285     {
286       xfree (parm->pubkey_url);
287       parm->pubkey_url = unescape_status_string (line);
288     }
289   else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen))
290     {
291       xfree (parm->login_data);
292       parm->login_data = unescape_status_string (line);
293     }
294   else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen))
295     {
296       parm->sig_counter = strtoul (line, NULL, 0);
297     }
298   else if (keywordlen == 10 && !memcmp (keyword, "CHV-STATUS", keywordlen))
299     {
300       char *p, *buf;
301
302       buf = p = unescape_status_string (line);
303       if (buf)
304         {
305           while (spacep (p))
306             p++;
307           parm->chv1_cached = atoi (p);
308           while (*p && !spacep (p))
309             p++;
310           while (spacep (p))
311             p++;
312           for (i=0; *p && i < 3; i++)
313             {
314               parm->chvmaxlen[i] = atoi (p);
315               while (*p && !spacep (p))
316                 p++;
317               while (spacep (p))
318                 p++;
319             }
320           for (i=0; *p && i < 3; i++)
321             {
322               parm->chvretry[i] = atoi (p);
323               while (*p && !spacep (p))
324                 p++;
325               while (spacep (p))
326                 p++;
327             }
328           xfree (buf);
329         }
330     }
331   else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
332     {
333       int no = atoi (line);
334       while (*line && !spacep (line))
335         line++;
336       while (spacep (line))
337         line++;
338       if (no == 1)
339         parm->fpr1valid = unhexify_fpr (line, parm->fpr1);
340       else if (no == 2)
341         parm->fpr2valid = unhexify_fpr (line, parm->fpr2);
342       else if (no == 3)
343         parm->fpr3valid = unhexify_fpr (line, parm->fpr3);
344     }
345   else if (keywordlen == 6 && !memcmp (keyword, "CA-FPR", keywordlen))
346     {
347       int no = atoi (line);
348       while (*line && !spacep (line))
349         line++;
350       while (spacep (line))
351         line++;
352       if (no == 1)
353         parm->cafpr1valid = unhexify_fpr (line, parm->cafpr1);
354       else if (no == 2)
355         parm->cafpr2valid = unhexify_fpr (line, parm->cafpr2);
356       else if (no == 3)
357         parm->cafpr3valid = unhexify_fpr (line, parm->cafpr3);
358     }
359   
360   return 0;
361 }
362
363 /* Call the agent to learn about a smartcard */
364 int
365 agent_learn (struct agent_card_info_s *info)
366 {
367   int rc;
368
369   rc = start_agent ();
370   if (rc)
371     return rc;
372
373   memset (info, 0, sizeof *info);
374   rc = assuan_transact (agent_ctx, "LEARN --send",
375                         NULL, NULL, default_inq_cb, NULL,
376                         learn_status_cb, info);
377   
378   return rc;
379 }
380
381 /* Call the agent to retrieve a data object.  This function returns
382    the data in the same structure as used by the learn command.  It is
383    allowed to update such a structure using this commmand. */
384 int
385 agent_scd_getattr (const char *name, struct agent_card_info_s *info)
386 {
387   int rc;
388   char line[ASSUAN_LINELENGTH];
389
390   if (!*name)
391     return gpg_error (GPG_ERR_INV_VALUE);
392
393   /* We assume that NAME does not need escaping. */
394   if (12 + strlen (name) > DIM(line)-1)
395     return gpg_error (GPG_ERR_TOO_LARGE);
396   stpcpy (stpcpy (line, "SCD GETATTR "), name); 
397
398   rc = start_agent ();
399   if (rc)
400     return rc;
401
402   rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, NULL,
403                         learn_status_cb, info);
404   
405   return rc;
406 }
407
408 \f
409 /* Send an setattr command to the SCdaemon.  SERIALNO is not actually
410    used here but required by gpg 1.4's implementation of this code in
411    cardglue.c. */
412 int
413 agent_scd_setattr (const char *name,
414                    const unsigned char *value, size_t valuelen,
415                    const char *serialno)
416 {
417   int rc;
418   char line[ASSUAN_LINELENGTH];
419   char *p;
420
421   if (!*name || !valuelen)
422     return gpg_error (GPG_ERR_INV_VALUE);
423
424   /* We assume that NAME does not need escaping. */
425   if (12 + strlen (name) > DIM(line)-1)
426     return gpg_error (GPG_ERR_TOO_LARGE);
427       
428   p = stpcpy (stpcpy (line, "SCD SETATTR "), name); 
429   *p++ = ' ';
430   for (; valuelen; value++, valuelen--)
431     {
432       if (p >= line + DIM(line)-5 )
433         return gpg_error (GPG_ERR_TOO_LARGE);
434       if (*value < ' ' || *value == '+' || *value == '%')
435         {
436           sprintf (p, "%%%02X", *value);
437           p += 3;
438         }
439       else if (*value == ' ')
440         *p++ = '+';
441       else
442         *p++ = *value;
443     }
444   *p = 0;
445
446   rc = start_agent ();
447   if (rc)
448     return rc;
449
450   rc = assuan_transact (agent_ctx, line, NULL, NULL, 
451                         default_inq_cb, NULL, NULL, NULL);
452   return rc;
453 }
454
455
456 \f
457 /* Handle a CERTDATA inquiry.  Note, we only send the data,
458    assuan_transact takes care of flushing and writing the END
459    command. */
460 static int
461 inq_writecert_parms (void *opaque, const char *line)
462 {
463   int rc;
464   struct writecert_parm_s *parm = opaque; 
465
466   if (!strncmp (line, "CERTDATA", 8) && (line[8]==' '||!line[8]))
467     {
468       rc = assuan_send_data (parm->ctx, parm->certdata, parm->certdatalen);
469     }
470   else
471     rc = default_inq_cb (opaque, line);
472
473   return rc;
474 }
475
476
477 /* Send a WRITECERT command to the SCdaemon. */
478 int 
479 agent_scd_writecert (const char *certidstr,
480                      const unsigned char *certdata, size_t certdatalen)
481 {
482   int rc;
483   char line[ASSUAN_LINELENGTH];
484   struct writecert_parm_s parms;
485
486   rc = start_agent ();
487   if (rc)
488     return rc;
489
490   memset (&parms, 0, sizeof parms);
491
492   snprintf (line, DIM(line)-1, "SCD WRITECERT %s", certidstr);
493   line[DIM(line)-1] = 0;
494   parms.ctx = agent_ctx;
495   parms.certdata = certdata;
496   parms.certdatalen = certdatalen;
497   
498   rc = assuan_transact (agent_ctx, line, NULL, NULL,
499                         inq_writecert_parms, &parms, NULL, NULL);
500
501   return rc;
502 }
503
504
505
506 \f
507 /* Handle a KEYDATA inquiry.  Note, we only send the data,
508    assuan_transact takes care of flushing and writing the end */
509 static int
510 inq_writekey_parms (void *opaque, const char *line)
511 {
512   int rc;
513   struct writekey_parm_s *parm = opaque; 
514
515   if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7]))
516     {
517       rc = assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen);
518     }
519   else
520     rc = default_inq_cb (opaque, line);
521
522   return rc;
523 }
524
525
526 /* Send a WRITEKEY command to the SCdaemon. */
527 int 
528 agent_scd_writekey (int keyno, const char *serialno,
529                     const unsigned char *keydata, size_t keydatalen)
530 {
531   int rc;
532   char line[ASSUAN_LINELENGTH];
533   struct writekey_parm_s parms;
534
535   rc = start_agent ();
536   if (rc)
537     return rc;
538
539   memset (&parms, 0, sizeof parms);
540
541   snprintf (line, DIM(line)-1, "SCD WRITEKEY --force OPENPGP.%d", keyno);
542   line[DIM(line)-1] = 0;
543   parms.ctx = agent_ctx;
544   parms.keydata = keydata;
545   parms.keydatalen = keydatalen;
546   
547   rc = assuan_transact (agent_ctx, line, NULL, NULL,
548                         inq_writekey_parms, &parms, NULL, NULL);
549
550   return rc;
551 }
552
553
554
555 \f
556 /* Status callback for the SCD GENKEY command. */
557 static int
558 scd_genkey_cb (void *opaque, const char *line)
559 {
560   struct agent_card_genkey_s *parm = opaque;
561   const char *keyword = line;
562   int keywordlen;
563   gpg_error_t rc;
564
565   log_debug ("got status line `%s'\n", line);
566   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
567     ;
568   while (spacep (line))
569     line++;
570
571   if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
572     {
573       parm->fprvalid = unhexify_fpr (line, parm->fpr);
574     }
575   if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
576     {
577       gcry_mpi_t a;
578       const char *name = line;
579
580       while (*line && !spacep (line))
581         line++;
582       while (spacep (line))
583         line++;
584
585       rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, line, 0, NULL);
586       if (rc)
587         log_error ("error parsing received key data: %s\n", gpg_strerror (rc));
588       else if (*name == 'n' && spacep (name+1))
589         parm->n = a;
590       else if (*name == 'e' && spacep (name+1))
591         parm->e = a;
592       else
593         {
594           log_info ("unknown parameter name in received key data\n");
595           gcry_mpi_release (a);
596         }
597     }
598   else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
599     {
600       parm->created_at = (u32)strtoul (line, NULL, 10);
601     }
602
603   return 0;
604 }
605
606 /* Send a GENKEY command to the SCdaemon.  SERIALNO is not used in
607    this implementation.  If CREATEDATE has been given, it will be
608    passed to SCDAEMON so that the key can be created with this
609    timestamp; note the user needs to use the returned timestamp as old
610    versions of scddaemon don't support this option.  */
611 int
612 agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
613                   const char *serialno, u32 createtime)
614 {
615   int rc;
616   char line[ASSUAN_LINELENGTH];
617   gnupg_isotime_t tbuf;
618
619   rc = start_agent ();
620   if (rc)
621     return rc;
622
623   if (createtime)
624     epoch2isotime (tbuf, createtime);
625   else
626     *tbuf = 0;
627
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;
634
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);
639   
640   return rc;
641 }
642
643 \f
644 static int
645 membuf_data_cb (void *opaque, const void *buffer, size_t length)
646 {
647   membuf_t *data = opaque;
648
649   if (buffer)
650     put_membuf (data, buffer, length);
651   return 0;
652 }
653   
654 /* Send a sign command to the scdaemon via gpg-agent's pass thru
655    mechanism. */
656 int
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)
660 {
661   int rc, i;
662   char *p, line[ASSUAN_LINELENGTH];
663   membuf_t data;
664   size_t len;
665
666   /* Note, hashalgo is not yet used but hardwired to SHA1 in SCdaemon. */
667
668   *r_buf = NULL;
669   *r_buflen = 0;
670
671   rc = start_agent ();
672   if (rc)
673     return rc;
674
675   if (indatalen*2 + 50 > DIM(line))
676     return gpg_error (GPG_ERR_GENERAL);
677
678   sprintf (line, "SCD SETDATA ");
679   p = line + strlen (line);
680   for (i=0; i < indatalen ; i++, p += 2 )
681     sprintf (p, "%02X", indata[i]);
682   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
683   if (rc)
684     return rc;
685
686   init_membuf (&data, 1024);
687 #if 0
688   if (!hashalgo) /* Temporary test hack. */
689     snprintf (line, DIM(line)-1, "SCD PKAUTH %s", serialno);
690   else
691 #endif
692     snprintf (line, DIM(line)-1, "SCD PKSIGN %s%s",
693               hashalgo == GCRY_MD_RMD160? "--hash=rmd160 " : "",
694               serialno);
695   line[DIM(line)-1] = 0;
696   rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data,
697                         default_inq_cb, NULL, NULL, NULL);
698   if (rc)
699     {
700       xfree (get_membuf (&data, &len));
701       return rc;
702     }
703   *r_buf = get_membuf (&data, r_buflen);
704
705   return 0;
706 }
707
708
709 /* Decrypt INDATA of length INDATALEN using the card identified by
710    SERIALNO.  Return the plaintext in a nwly allocated buffer stored
711    at the address of R_BUF. 
712
713    Note, we currently support only RSA or more exactly algorithms
714    taking one input data element. */
715 int
716 agent_scd_pkdecrypt (const char *serialno,
717                      const unsigned char *indata, size_t indatalen,
718                      unsigned char **r_buf, size_t *r_buflen)
719 {
720   int rc, i;
721   char *p, line[ASSUAN_LINELENGTH];
722   membuf_t data;
723   size_t len;
724
725   *r_buf = NULL;
726   rc = start_agent ();
727   if (rc)
728     return rc;
729
730   /* FIXME: use secure memory where appropriate */
731   if (indatalen*2 + 50 > DIM(line))
732     return gpg_error (GPG_ERR_GENERAL);
733
734   sprintf (line, "SCD SETDATA ");
735   p = line + strlen (line);
736   for (i=0; i < indatalen ; i++, p += 2 )
737     sprintf (p, "%02X", indata[i]);
738   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
739   if (rc)
740     return rc;
741
742   init_membuf (&data, 1024);
743   snprintf (line, DIM(line)-1, "SCD PKDECRYPT %s", serialno);
744   line[DIM(line)-1] = 0;
745   rc = assuan_transact (agent_ctx, line,
746                         membuf_data_cb, &data,
747                         default_inq_cb, NULL, NULL, NULL);
748   if (rc)
749     {
750       xfree (get_membuf (&data, &len));
751       return rc;
752     }
753   *r_buf = get_membuf (&data, r_buflen);
754   if (!*r_buf)
755     return gpg_error (GPG_ERR_ENOMEM);
756
757   return 0;
758 }
759
760
761 /* Change the PIN of an OpenPGP card or reset the retry counter.
762    CHVNO 1: Change the PIN
763          2: For v1 cards: Same as 1.
764             For v2 cards: Reset the PIN using the Reset Code.
765          3: Change the admin PIN
766        101: Set a new PIN and reset the retry counter
767        102: For v1 cars: Same as 101.
768             For v2 cards: Set a new Reset Code.
769    SERIALNO is not used.
770  */
771 int
772 agent_scd_change_pin (int chvno, const char *serialno)
773 {
774   int rc;
775   char line[ASSUAN_LINELENGTH];
776   const char *reset = "";
777
778   if (chvno >= 100)
779     reset = "--reset";
780   chvno %= 100;
781
782   rc = start_agent ();
783   if (rc)
784     return rc;
785
786   snprintf (line, DIM(line)-1, "SCD PASSWD %s %d", reset, chvno);
787   line[DIM(line)-1] = 0;
788   rc = assuan_transact (agent_ctx, line, NULL, NULL,
789                         default_inq_cb, NULL, NULL, NULL);
790   return rc;
791 }
792
793
794 /* Perform a CHECKPIN operation.  SERIALNO should be the serial
795    number of the card - optionally followed by the fingerprint;
796    however the fingerprint is ignored here. */
797 int
798 agent_scd_checkpin  (const char *serialno)
799 {
800   int rc;
801   char line[ASSUAN_LINELENGTH];
802
803   rc = start_agent ();
804   if (rc)
805     return rc;
806
807   snprintf (line, DIM(line)-1, "SCD CHECKPIN %s", serialno);
808   line[DIM(line)-1] = 0;
809   return assuan_transact (agent_ctx, line,
810                           NULL, NULL,
811                           default_inq_cb, NULL, NULL, NULL);
812 }
813
814
815 /* Dummy function, only used by the gpg 1.4 implementation. */
816 void
817 agent_clear_pin_cache (const char *sn)
818 {
819
820 }
821
822
823
824 \f
825 /* Note: All strings shall be UTF-8. On success the caller needs to
826    free the string stored at R_PASSPHRASE. On error NULL will be
827    stored at R_PASSPHRASE and an appropriate fpf error code
828    returned. */
829 gpg_error_t
830 agent_get_passphrase (const char *cache_id,
831                       const char *err_msg,
832                       const char *prompt,
833                       const char *desc_msg,
834                       char **r_passphrase)
835 {
836   int rc;
837   char *line, *p;
838   char cmd[] = "GET_PASSPHRASE --data -- ";
839   membuf_t data;
840
841   *r_passphrase = NULL;
842
843   rc = start_agent ();
844   if (rc)
845     return rc;
846
847   /* We allocate 3 times the needed space for the texts so that
848      there is enough space for escaping. */
849   line = xtrymalloc ( strlen (cmd) + 1
850                       + (cache_id? 3*strlen (cache_id): 1) + 1
851                       + (err_msg?  3*strlen (err_msg): 1) + 1
852                       + (prompt?   3*strlen (prompt): 1) + 1
853                       + (desc_msg? 3*strlen (desc_msg): 1) + 1
854                       + 1);
855   if (!line)
856     return gpg_error_from_syserror ();
857
858   p = stpcpy (line, cmd);
859   if (cache_id && *cache_id)
860     p = percent_plus_escape (p, cache_id);
861   else
862     *p++ = 'X';
863   *p++ = ' ';
864
865   if (err_msg && *err_msg)
866     p = percent_plus_escape (p, err_msg);
867   else
868     *p++ = 'X';
869   *p++ = ' ';
870
871   if (prompt && *prompt)
872     p = percent_plus_escape (p, prompt);
873   else
874     *p++ = 'X'; 
875   *p++ = ' ';
876
877   if (desc_msg && *desc_msg)
878     p = percent_plus_escape (p, desc_msg);
879   else
880     *p++ = 'X';
881   *p = 0;
882
883   init_membuf_secure (&data, 64);
884   rc = assuan_transact (agent_ctx, line, 
885                         membuf_data_cb, &data,
886                         default_inq_cb, NULL, NULL, NULL);
887
888   if (rc)
889     xfree (get_membuf (&data, NULL));
890   else 
891     {
892       put_membuf (&data, "", 1);
893       *r_passphrase = get_membuf (&data, NULL);
894       if (!*r_passphrase)
895         rc = gpg_error_from_syserror ();
896     }
897   xfree (line);
898   return rc;
899 }
900
901
902 gpg_error_t
903 agent_clear_passphrase (const char *cache_id)
904 {
905   int rc;
906   char line[ASSUAN_LINELENGTH];
907
908   if (!cache_id || !*cache_id)
909     return 0;
910
911   rc = start_agent ();
912   if (rc)
913     return rc;
914
915   snprintf (line, DIM(line)-1, "CLEAR_PASSPHRASE %s", cache_id);
916   line[DIM(line)-1] = 0;
917   return assuan_transact (agent_ctx, line, NULL, NULL,
918                           default_inq_cb, NULL, NULL, NULL);
919 }