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