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