Enhanced last patch.
[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
148 /* Take a 20 byte hexencoded string and put it into the the provided
149    20 byte buffer FPR in binary format. */
150 static int
151 unhexify_fpr (const char *hexstr, unsigned char *fpr)
152 {
153   const char *s;
154   int n;
155
156   for (s=hexstr, n=0; hexdigitp (s); s++, n++)
157     ;
158   if (*s || (n != 40))
159     return 0; /* no fingerprint (invalid or wrong length). */
160   n /= 2;
161   for (s=hexstr, n=0; *s; s += 2, n++)
162     fpr[n] = xtoi_2 (s);
163   return 1; /* okay */
164 }
165
166 /* Take the serial number from LINE and return it verbatim in a newly
167    allocated string.  We make sure that only hex characters are
168    returned. */
169 static char *
170 store_serialno (const char *line)
171 {
172   const char *s;
173   char *p;
174
175   for (s=line; hexdigitp (s); s++)
176     ;
177   p = xtrymalloc (s + 1 - line);
178   if (p)
179     {
180       memcpy (p, line, s-line);
181       p[s-line] = 0;
182     }
183   return p;
184 }
185
186
187 \f
188 /* This is a dummy data line callback.  */
189 static int
190 dummy_data_cb (void *opaque, const void *buffer, size_t length)
191 {
192   (void)opaque;
193   (void)buffer;
194   (void)length;
195   return 0;
196 }
197
198
199 /* This is the default inquiry callback.  It mainly handles the
200    Pinentry notifications.  */
201 static int
202 default_inq_cb (void *opaque, const char *line)
203 {
204   (void)opaque;
205
206   if (!strncmp (line, "PINENTRY_LAUNCHED", 17) && (line[17]==' '||!line[17]))
207     {
208       /* There is no working server mode yet thus we use
209          AllowSetForegroundWindow window right here.  We might want to
210          do this anyway in case gpg is called on the console. */
211       gnupg_allow_set_foregound_window ((pid_t)strtoul (line+17, NULL, 10));
212       /* We do not pass errors to avoid breaking other code.  */
213     }
214   else
215     log_debug ("ignoring gpg-agent inquiry `%s'\n", line);
216
217   return 0;
218 }
219
220
221
222 /* Release the card info structure INFO. */
223 void
224 agent_release_card_info (struct agent_card_info_s *info)
225 {
226   if (!info)
227     return;
228
229   xfree (info->serialno); info->serialno = NULL;
230   xfree (info->apptype); info->apptype = NULL;
231   xfree (info->disp_name); info->disp_name = NULL;
232   xfree (info->disp_lang); info->disp_lang = NULL;
233   xfree (info->pubkey_url); info->pubkey_url = NULL;
234   xfree (info->login_data); info->login_data = NULL;
235   info->cafpr1valid = info->cafpr2valid = info->cafpr3valid = 0;
236   info->fpr1valid = info->fpr2valid = info->fpr3valid = 0;
237 }
238
239 static int
240 learn_status_cb (void *opaque, const char *line)
241 {
242   struct agent_card_info_s *parm = opaque;
243   const char *keyword = line;
244   int keywordlen;
245   int i;
246
247   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
248     ;
249   while (spacep (line))
250     line++;
251
252   if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
253     {
254       xfree (parm->serialno);
255       parm->serialno = store_serialno (line);
256       parm->is_v2 = (strlen (parm->serialno) >= 16 
257                      && xtoi_2 (parm->serialno+12) >= 2 );
258     }
259   else if (keywordlen == 7 && !memcmp (keyword, "APPTYPE", keywordlen))
260     {
261       xfree (parm->apptype);
262       parm->apptype = unescape_status_string (line);
263     }
264   else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
265     {
266       xfree (parm->disp_name);
267       parm->disp_name = unescape_status_string (line);
268     }
269   else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen))
270     {
271       xfree (parm->disp_lang);
272       parm->disp_lang = unescape_status_string (line);
273     }
274   else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen))
275     {
276       parm->disp_sex = *line == '1'? 1 : *line == '2' ? 2: 0;
277     }
278   else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
279     {
280       xfree (parm->pubkey_url);
281       parm->pubkey_url = unescape_status_string (line);
282     }
283   else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen))
284     {
285       xfree (parm->login_data);
286       parm->login_data = unescape_status_string (line);
287     }
288   else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen))
289     {
290       parm->sig_counter = strtoul (line, NULL, 0);
291     }
292   else if (keywordlen == 10 && !memcmp (keyword, "CHV-STATUS", keywordlen))
293     {
294       char *p, *buf;
295
296       buf = p = unescape_status_string (line);
297       if (buf)
298         {
299           while (spacep (p))
300             p++;
301           parm->chv1_cached = atoi (p);
302           while (*p && !spacep (p))
303             p++;
304           while (spacep (p))
305             p++;
306           for (i=0; *p && i < 3; i++)
307             {
308               parm->chvmaxlen[i] = atoi (p);
309               while (*p && !spacep (p))
310                 p++;
311               while (spacep (p))
312                 p++;
313             }
314           for (i=0; *p && i < 3; i++)
315             {
316               parm->chvretry[i] = atoi (p);
317               while (*p && !spacep (p))
318                 p++;
319               while (spacep (p))
320                 p++;
321             }
322           xfree (buf);
323         }
324     }
325   else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
326     {
327       int no = atoi (line);
328       while (*line && !spacep (line))
329         line++;
330       while (spacep (line))
331         line++;
332       if (no == 1)
333         parm->fpr1valid = unhexify_fpr (line, parm->fpr1);
334       else if (no == 2)
335         parm->fpr2valid = unhexify_fpr (line, parm->fpr2);
336       else if (no == 3)
337         parm->fpr3valid = unhexify_fpr (line, parm->fpr3);
338     }
339   else if (keywordlen == 6 && !memcmp (keyword, "CA-FPR", keywordlen))
340     {
341       int no = atoi (line);
342       while (*line && !spacep (line))
343         line++;
344       while (spacep (line))
345         line++;
346       if (no == 1)
347         parm->cafpr1valid = unhexify_fpr (line, parm->cafpr1);
348       else if (no == 2)
349         parm->cafpr2valid = unhexify_fpr (line, parm->cafpr2);
350       else if (no == 3)
351         parm->cafpr3valid = unhexify_fpr (line, parm->cafpr3);
352     }
353   
354   return 0;
355 }
356
357 /* Call the agent to learn about a smartcard */
358 int
359 agent_learn (struct agent_card_info_s *info)
360 {
361   int rc;
362
363   rc = start_agent ();
364   if (rc)
365     return rc;
366
367   memset (info, 0, sizeof *info);
368   rc = assuan_transact (agent_ctx, "LEARN --send",
369                         dummy_data_cb, NULL, default_inq_cb, NULL,
370                         learn_status_cb, info);
371   
372   return rc;
373 }
374
375 /* Call the agent to retrieve a data object.  This function returns
376    the data in the same structure as used by the learn command.  It is
377    allowed to update such a structure using this commmand. */
378 int
379 agent_scd_getattr (const char *name, struct agent_card_info_s *info)
380 {
381   int rc;
382   char line[ASSUAN_LINELENGTH];
383
384   if (!*name)
385     return gpg_error (GPG_ERR_INV_VALUE);
386
387   /* We assume that NAME does not need escaping. */
388   if (12 + strlen (name) > DIM(line)-1)
389     return gpg_error (GPG_ERR_TOO_LARGE);
390   stpcpy (stpcpy (line, "SCD GETATTR "), name); 
391
392   rc = start_agent ();
393   if (rc)
394     return rc;
395
396   rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, NULL,
397                         learn_status_cb, info);
398   
399   return rc;
400 }
401
402 \f
403 /* Send an setattr command to the SCdaemon.  SERIALNO is not actually
404    used here but required by gpg 1.4's implementation of this code in
405    cardglue.c. */
406 int
407 agent_scd_setattr (const char *name,
408                    const unsigned char *value, size_t valuelen,
409                    const char *serialno)
410 {
411   int rc;
412   char line[ASSUAN_LINELENGTH];
413   char *p;
414
415   (void)serialno;
416
417   if (!*name || !valuelen)
418     return gpg_error (GPG_ERR_INV_VALUE);
419
420   /* We assume that NAME does not need escaping. */
421   if (12 + strlen (name) > DIM(line)-1)
422     return gpg_error (GPG_ERR_TOO_LARGE);
423       
424   p = stpcpy (stpcpy (line, "SCD SETATTR "), name); 
425   *p++ = ' ';
426   for (; valuelen; value++, valuelen--)
427     {
428       if (p >= line + DIM(line)-5 )
429         return gpg_error (GPG_ERR_TOO_LARGE);
430       if (*value < ' ' || *value == '+' || *value == '%')
431         {
432           sprintf (p, "%%%02X", *value);
433           p += 3;
434         }
435       else if (*value == ' ')
436         *p++ = '+';
437       else
438         *p++ = *value;
439     }
440   *p = 0;
441
442   rc = start_agent ();
443   if (rc)
444     return rc;
445
446   rc = assuan_transact (agent_ctx, line, NULL, NULL, 
447                         default_inq_cb, NULL, NULL, NULL);
448   return rc;
449 }
450
451
452 \f
453 /* Handle a CERTDATA inquiry.  Note, we only send the data,
454    assuan_transact takes care of flushing and writing the END
455    command. */
456 static int
457 inq_writecert_parms (void *opaque, const char *line)
458 {
459   int rc;
460   struct writecert_parm_s *parm = opaque; 
461
462   if (!strncmp (line, "CERTDATA", 8) && (line[8]==' '||!line[8]))
463     {
464       rc = assuan_send_data (parm->ctx, parm->certdata, parm->certdatalen);
465     }
466   else
467     rc = default_inq_cb (opaque, line);
468
469   return rc;
470 }
471
472
473 /* Send a WRITECERT command to the SCdaemon. */
474 int 
475 agent_scd_writecert (const char *certidstr,
476                      const unsigned char *certdata, size_t certdatalen)
477 {
478   int rc;
479   char line[ASSUAN_LINELENGTH];
480   struct writecert_parm_s parms;
481
482   rc = start_agent ();
483   if (rc)
484     return rc;
485
486   memset (&parms, 0, sizeof parms);
487
488   snprintf (line, DIM(line)-1, "SCD WRITECERT %s", certidstr);
489   line[DIM(line)-1] = 0;
490   parms.ctx = agent_ctx;
491   parms.certdata = certdata;
492   parms.certdatalen = certdatalen;
493   
494   rc = assuan_transact (agent_ctx, line, NULL, NULL,
495                         inq_writecert_parms, &parms, NULL, NULL);
496
497   return rc;
498 }
499
500
501
502 \f
503 /* Handle a KEYDATA inquiry.  Note, we only send the data,
504    assuan_transact takes care of flushing and writing the end */
505 static int
506 inq_writekey_parms (void *opaque, const char *line)
507 {
508   int rc;
509   struct writekey_parm_s *parm = opaque; 
510
511   if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7]))
512     {
513       rc = assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen);
514     }
515   else
516     rc = default_inq_cb (opaque, line);
517
518   return rc;
519 }
520
521
522 /* Send a WRITEKEY command to the SCdaemon. */
523 int 
524 agent_scd_writekey (int keyno, const char *serialno,
525                     const unsigned char *keydata, size_t keydatalen)
526 {
527   int rc;
528   char line[ASSUAN_LINELENGTH];
529   struct writekey_parm_s parms;
530
531   (void)serialno;
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   (void)serialno;
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   /* Send the serialno command to initialize the connection. We don't
679      care about the data returned.  If the card has already been
680      initialized, this is a very fast command.  We request the openpgp
681      card because that is waht we expect. */
682   rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
683                         NULL, NULL, NULL, NULL, NULL, NULL);
684   if (rc)
685     return rc;
686
687   sprintf (line, "SCD SETDATA ");
688   p = line + strlen (line);
689   for (i=0; i < indatalen ; i++, p += 2 )
690     sprintf (p, "%02X", indata[i]);
691   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
692   if (rc)
693     return rc;
694
695   init_membuf (&data, 1024);
696 #if 0
697   if (!hashalgo) /* Temporary test hack. */
698     snprintf (line, DIM(line)-1, "SCD PKAUTH %s", serialno);
699   else
700 #endif
701     snprintf (line, DIM(line)-1, "SCD PKSIGN %s%s",
702               hashalgo == GCRY_MD_RMD160? "--hash=rmd160 " : "",
703               serialno);
704   line[DIM(line)-1] = 0;
705   rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data,
706                         default_inq_cb, NULL, NULL, NULL);
707   if (rc)
708     {
709       xfree (get_membuf (&data, &len));
710       return rc;
711     }
712   *r_buf = get_membuf (&data, r_buflen);
713
714   return 0;
715 }
716
717
718 /* Decrypt INDATA of length INDATALEN using the card identified by
719    SERIALNO.  Return the plaintext in a nwly allocated buffer stored
720    at the address of R_BUF. 
721
722    Note, we currently support only RSA or more exactly algorithms
723    taking one input data element. */
724 int
725 agent_scd_pkdecrypt (const char *serialno,
726                      const unsigned char *indata, size_t indatalen,
727                      unsigned char **r_buf, size_t *r_buflen)
728 {
729   int rc, i;
730   char *p, line[ASSUAN_LINELENGTH];
731   membuf_t data;
732   size_t len;
733
734   *r_buf = NULL;
735   rc = start_agent ();
736   if (rc)
737     return rc;
738
739   /* FIXME: use secure memory where appropriate */
740   if (indatalen*2 + 50 > DIM(line))
741     return gpg_error (GPG_ERR_GENERAL);
742
743   /* Send the serialno command to initialize the connection. We don't
744      care about the data returned.  If the card has already been
745      initialized, this is a very fast command.  We request the openpgp
746      card because that is waht we expect. */
747   rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
748                         NULL, NULL, NULL, NULL, NULL, NULL);
749   if (rc)
750     return rc;
751
752   sprintf (line, "SCD SETDATA ");
753   p = line + strlen (line);
754   for (i=0; i < indatalen ; i++, p += 2 )
755     sprintf (p, "%02X", indata[i]);
756   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
757   if (rc)
758     return rc;
759
760   init_membuf (&data, 1024);
761   snprintf (line, DIM(line)-1, "SCD PKDECRYPT %s", serialno);
762   line[DIM(line)-1] = 0;
763   rc = assuan_transact (agent_ctx, line,
764                         membuf_data_cb, &data,
765                         default_inq_cb, NULL, NULL, NULL);
766   if (rc)
767     {
768       xfree (get_membuf (&data, &len));
769       return rc;
770     }
771   *r_buf = get_membuf (&data, r_buflen);
772   if (!*r_buf)
773     return gpg_error (GPG_ERR_ENOMEM);
774
775   return 0;
776 }
777
778
779 /* Change the PIN of an OpenPGP card or reset the retry counter.
780    CHVNO 1: Change the PIN
781          2: For v1 cards: Same as 1.
782             For v2 cards: Reset the PIN using the Reset Code.
783          3: Change the admin PIN
784        101: Set a new PIN and reset the retry counter
785        102: For v1 cars: Same as 101.
786             For v2 cards: Set a new Reset Code.
787    SERIALNO is not used.
788  */
789 int
790 agent_scd_change_pin (int chvno, const char *serialno)
791 {
792   int rc;
793   char line[ASSUAN_LINELENGTH];
794   const char *reset = "";
795
796   (void)serialno;
797
798   if (chvno >= 100)
799     reset = "--reset";
800   chvno %= 100;
801
802   rc = start_agent ();
803   if (rc)
804     return rc;
805
806   snprintf (line, DIM(line)-1, "SCD PASSWD %s %d", reset, chvno);
807   line[DIM(line)-1] = 0;
808   rc = assuan_transact (agent_ctx, line, NULL, NULL,
809                         default_inq_cb, NULL, NULL, NULL);
810   return rc;
811 }
812
813
814 /* Perform a CHECKPIN operation.  SERIALNO should be the serial
815    number of the card - optionally followed by the fingerprint;
816    however the fingerprint is ignored here. */
817 int
818 agent_scd_checkpin  (const char *serialno)
819 {
820   int rc;
821   char line[ASSUAN_LINELENGTH];
822
823   rc = start_agent ();
824   if (rc)
825     return rc;
826
827   snprintf (line, DIM(line)-1, "SCD CHECKPIN %s", serialno);
828   line[DIM(line)-1] = 0;
829   return assuan_transact (agent_ctx, line,
830                           NULL, NULL,
831                           default_inq_cb, NULL, NULL, NULL);
832 }
833
834
835 /* Dummy function, only used by the gpg 1.4 implementation. */
836 void
837 agent_clear_pin_cache (const char *sn)
838 {
839   (void)sn;
840 }
841
842
843
844 \f
845 /* Note: All strings shall be UTF-8. On success the caller needs to
846    free the string stored at R_PASSPHRASE. On error NULL will be
847    stored at R_PASSPHRASE and an appropriate fpf error code
848    returned. */
849 gpg_error_t
850 agent_get_passphrase (const char *cache_id,
851                       const char *err_msg,
852                       const char *prompt,
853                       const char *desc_msg,
854                       int repeat,
855                       char **r_passphrase)
856 {
857   int rc;
858   char line[ASSUAN_LINELENGTH];
859   char *arg1 = NULL;
860   char *arg2 = NULL;  
861   char *arg3 = NULL; 
862   char *arg4 = NULL;
863   membuf_t data;
864
865   *r_passphrase = NULL;
866
867   rc = start_agent ();
868   if (rc)
869     return rc;
870
871   /* Check that the gpg-agent understands the repeat option.  */
872   if (assuan_transact (agent_ctx, 
873                        "GETINFO cmd_has_option GET_PASSPHRASE repeat",
874                        NULL, NULL, NULL, NULL, NULL, NULL))
875     return gpg_error (GPG_ERR_NOT_SUPPORTED);
876
877   if (cache_id && *cache_id)
878     if (!(arg1 = percent_plus_escape (cache_id)))
879       goto no_mem;
880   if (err_msg && *err_msg)
881     if (!(arg2 = percent_plus_escape (err_msg)))
882       goto no_mem;
883   if (prompt && *prompt)
884     if (!(arg3 = percent_plus_escape (prompt)))
885       goto no_mem;
886   if (desc_msg && *desc_msg)
887     if (!(arg4 = percent_plus_escape (desc_msg)))
888       goto no_mem;
889
890   snprintf (line, DIM(line)-1, 
891             "GET_PASSPHRASE --data --repeat=%d -- %s %s %s %s", 
892             repeat, 
893             arg1? arg1:"X",
894             arg2? arg2:"X",
895             arg3? arg3:"X",
896             arg4? arg4:"X");
897   line[DIM(line)-1] = 0;
898   xfree (arg1);
899   xfree (arg2);
900   xfree (arg3);
901   xfree (arg4);
902
903   init_membuf_secure (&data, 64);
904   rc = assuan_transact (agent_ctx, line, 
905                         membuf_data_cb, &data,
906                         default_inq_cb, NULL, NULL, NULL);
907
908   if (rc)
909     xfree (get_membuf (&data, NULL));
910   else 
911     {
912       put_membuf (&data, "", 1);
913       *r_passphrase = get_membuf (&data, NULL);
914       if (!*r_passphrase)
915         rc = gpg_error_from_syserror ();
916     }
917   return rc;
918  no_mem:
919   rc = gpg_error_from_syserror ();
920   xfree (arg1);
921   xfree (arg2);
922   xfree (arg3);
923   xfree (arg4);
924   return rc;
925 }
926
927
928 gpg_error_t
929 agent_clear_passphrase (const char *cache_id)
930 {
931   int rc;
932   char line[ASSUAN_LINELENGTH];
933
934   if (!cache_id || !*cache_id)
935     return 0;
936
937   rc = start_agent ();
938   if (rc)
939     return rc;
940
941   snprintf (line, DIM(line)-1, "CLEAR_PASSPHRASE %s", cache_id);
942   line[DIM(line)-1] = 0;
943   return assuan_transact (agent_ctx, line, NULL, NULL,
944                           default_inq_cb, NULL, NULL, NULL);
945 }