Cleanups.
[gnupg.git] / g10 / call-agent.c
1 /* call-agent.c - divert operations to the agent
2  * Copyright (C) 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19  * USA.
20  */
21
22 #if 0  /* let Emacs display a red warning */
23 #error fixme: this shares a lot of code with the file in ../sm
24 #endif
25
26 #include <config.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <unistd.h> 
32 #include <time.h>
33 #include <assert.h>
34 #ifdef HAVE_LOCALE_H
35 #include <locale.h>
36 #endif
37 #include <assuan.h>
38
39 #include "gpg.h"
40 #include "util.h"
41 #include "membuf.h"
42 #include "options.h"
43 #include "i18n.h"
44 #include "asshelp.h"
45 #include "call-agent.h"
46
47 #ifndef DBG_ASSUAN
48 # define DBG_ASSUAN 1
49 #endif
50
51 static assuan_context_t agent_ctx = NULL;
52 static int force_pipe_server; 
53
54 struct cipher_parm_s 
55 {
56   assuan_context_t ctx;
57   const char *ciphertext;
58   size_t ciphertextlen;
59 };
60
61 struct writekey_parm_s
62 {
63   assuan_context_t ctx;
64   const unsigned char *keydata;
65   size_t keydatalen;
66 };
67
68 struct genkey_parm_s 
69 {
70   assuan_context_t ctx;
71   const char *sexp;
72   size_t sexplen;
73 };
74
75
76 \f
77 /* Try to connect to the agent via socket or fork it off and work by
78    pipes.  Handle the server's initial greeting */
79 static int
80 start_agent (void)
81 {
82   int rc = 0;
83   char *infostr, *p;
84   assuan_context_t ctx;
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   infostr = force_pipe_server? NULL : getenv ("GPG_AGENT_INFO");
91   if (!infostr || !*infostr)
92     {
93       const char *pgmname;
94       const char *argv[3];
95       int no_close_list[3];
96       int i;
97
98       if (opt.verbose)
99         log_info (_("no running gpg-agent - starting one\n"));
100
101       if (fflush (NULL))
102         {
103           gpg_error_t tmperr = gpg_error_from_syserror ();
104           log_error ("error flushing pending output: %s\n", strerror (errno));
105           return tmperr;
106         }
107
108       if (!opt.agent_program || !*opt.agent_program)
109         opt.agent_program = GNUPG_DEFAULT_AGENT;
110       if ( !(pgmname = strrchr (opt.agent_program, '/')))
111         pgmname = opt.agent_program;
112       else
113         pgmname++;
114
115       argv[0] = pgmname;
116       argv[1] = "--server";
117       argv[2] = NULL;
118
119       i=0;
120       if (log_get_fd () != -1)
121         no_close_list[i++] = log_get_fd ();
122       no_close_list[i++] = fileno (stderr);
123       no_close_list[i] = -1;
124
125       /* connect to the agent and perform initial handshaking */
126       rc = assuan_pipe_connect (&ctx, opt.agent_program, argv,
127                                 no_close_list);
128     }
129   else
130     {
131       int prot;
132       int pid;
133
134       infostr = xstrdup (infostr);
135       if ( !(p = strchr (infostr, ':')) || p == infostr)
136         {
137           log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
138           xfree (infostr);
139           force_pipe_server = 1;
140           return start_agent ();
141         }
142       *p++ = 0;
143       pid = atoi (p);
144       while (*p && *p != ':')
145         p++;
146       prot = *p? atoi (p+1) : 0;
147       if (prot != 1)
148         {
149           log_error (_("gpg-agent protocol version %d is not supported\n"),
150                      prot);
151           xfree (infostr);
152           force_pipe_server = 1;
153           return start_agent ();
154         }
155
156       rc = assuan_socket_connect (&ctx, infostr, pid);
157       xfree (infostr);
158       if (gpg_err_code (rc) == GPG_ERR_ASS_CONNECT_FAILED)
159         {
160           log_error (_("can't connect to the agent - trying fall back\n"));
161           force_pipe_server = 1;
162           return start_agent ();
163         }
164     }
165
166   if (rc)
167     {
168       log_error ("can't connect to the agent: %s\n", gpg_strerror (rc));
169       return gpg_error (GPG_ERR_NO_AGENT);
170     }
171   agent_ctx = ctx;
172
173   if (DBG_ASSUAN)
174     log_debug ("connection to agent established\n");
175
176   rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL,NULL);
177   if (rc)
178     return rc;
179
180   return send_pinentry_environment (agent_ctx, GPG_ERR_SOURCE_DEFAULT,
181                                     opt.display, opt.ttyname, opt.ttytype,
182                                     opt.lc_ctype, opt.lc_messages);
183 }
184
185
186 /* Return a new malloced string by unescaping the string S.  Escaping
187    is percent escaping and '+'/space mapping.  A binary nul will
188    silently be replaced by a 0xFF.  Function returns NULL to indicate
189    an out of memory status. */
190 static char *
191 unescape_status_string (const unsigned char *s)
192 {
193   char *buffer, *d;
194
195   buffer = d = xtrymalloc (strlen (s)+1);
196   if (!buffer)
197     return NULL;
198   while (*s)
199     {
200       if (*s == '%' && s[1] && s[2])
201         { 
202           s++;
203           *d = xtoi_2 (s);
204           if (!*d)
205             *d = '\xff';
206           d++;
207           s += 2;
208         }
209       else if (*s == '+')
210         {
211           *d++ = ' ';
212           s++;
213         }
214       else
215         *d++ = *s++;
216     }
217   *d = 0; 
218   return buffer;
219 }
220
221 /* Take a 20 byte hexencoded string and put it into the the provided
222    20 byte buffer FPR in binary format. */
223 static int
224 unhexify_fpr (const char *hexstr, unsigned char *fpr)
225 {
226   const char *s;
227   int n;
228
229   for (s=hexstr, n=0; hexdigitp (s); s++, n++)
230     ;
231   if (*s || (n != 40))
232     return 0; /* no fingerprint (invalid or wrong length). */
233   n /= 2;
234   for (s=hexstr, n=0; *s; s += 2, n++)
235     fpr[n] = xtoi_2 (s);
236   return 1; /* okay */
237 }
238
239 /* Take the serial number from LINE and return it verbatim in a newly
240    allocated string.  We make sure that only hex characters are
241    returned. */
242 static char *
243 store_serialno (const char *line)
244 {
245   const char *s;
246   char *p;
247
248   for (s=line; hexdigitp (s); s++)
249     ;
250   p = xtrymalloc (s + 1 - line);
251   if (p)
252     {
253       memcpy (p, line, s-line);
254       p[s-line] = 0;
255     }
256   return p;
257 }
258
259
260 \f
261 #if 0
262 /* Handle a KEYPARMS inquiry.  Note, we only send the data,
263    assuan_transact takes care of flushing and writing the end */
264 static int
265 inq_genkey_parms (void *opaque, const char *keyword)
266 {
267   struct genkey_parm_s *parm = opaque; 
268   int rc;
269
270   rc = assuan_send_data (parm->ctx, parm->sexp, parm->sexplen);
271   return rc; 
272 }
273
274
275 \f
276 /* Call the agent to generate a new key */
277 int
278 agent_genkey (KsbaConstSexp keyparms, KsbaSexp *r_pubkey)
279 {
280   int rc;
281   struct genkey_parm_s gk_parm;
282   membuf_t data;
283   size_t len;
284   char *buf;
285
286   *r_pubkey = NULL;
287   rc = start_agent ();
288   if (rc)
289     return rc;
290
291   rc = assuan_transact (agent_ctx, "RESET", NULL, NULL,
292                         NULL, NULL, NULL, NULL);
293   if (rc)
294     return rc;
295
296   init_membuf (&data, 1024);
297   gk_parm.ctx = agent_ctx;
298   gk_parm.sexp = keyparms;
299   gk_parm.sexplen = gcry_sexp_canon_len (keyparms, 0, NULL, NULL);
300   if (!gk_parm.sexplen)
301     return gpg_error (GPG_ERR_INV_VALUE);
302   rc = assuan_transact (agent_ctx, "GENKEY",
303                         membuf_data_cb, &data, 
304                         inq_genkey_parms, &gk_parm, NULL, NULL);
305   if (rc)
306     {
307       xfree (get_membuf (&data, &len));
308       return rc;
309     }
310   buf = get_membuf (&data, &len);
311   if (!buf)
312     return gpg_error (GPG_ERR_ENOMEM);
313   if (!gcry_sexp_canon_len (buf, len, NULL, NULL))
314     {
315       xfree (buf);
316       return gpg_error (GPG_ERR_INV_SEXP);
317     }
318   *r_pubkey = buf;
319   return 0;
320 }
321 #endif /*0*/
322
323
324 \f
325 /* Ask the agent whether the corresponding secret key is available for
326    the given keygrip. */
327 int
328 agent_havekey (const char *hexkeygrip)
329 {
330   int rc;
331   char line[ASSUAN_LINELENGTH];
332
333   rc = start_agent ();
334   if (rc)
335     return rc;
336
337   if (!hexkeygrip || strlen (hexkeygrip) != 40)
338     return gpg_error (GPG_ERR_INV_VALUE);
339
340   snprintf (line, DIM(line)-1, "HAVEKEY %s", hexkeygrip);
341   line[DIM(line)-1] = 0;
342
343   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
344   return rc;
345 }
346
347 \f
348 /* Release the card info structure INFO. */
349 void
350 agent_release_card_info (struct agent_card_info_s *info)
351 {
352   if (!info)
353     return;
354
355   xfree (info->serialno); info->serialno = NULL;
356   xfree (info->disp_name); info->disp_name = NULL;
357   xfree (info->disp_lang); info->disp_lang = NULL;
358   xfree (info->pubkey_url); info->pubkey_url = NULL;
359   xfree (info->login_data); info->login_data = NULL;
360   info->cafpr1valid = info->cafpr2valid = info->cafpr3valid = 0;
361   info->fpr1valid = info->fpr2valid = info->fpr3valid = 0;
362 }
363
364 static int
365 learn_status_cb (void *opaque, const char *line)
366 {
367   struct agent_card_info_s *parm = opaque;
368   const char *keyword = line;
369   int keywordlen;
370   int i;
371
372   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
373     ;
374   while (spacep (line))
375     line++;
376
377   if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
378     {
379       xfree (parm->serialno);
380       parm->serialno = store_serialno (line);
381     }
382   else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
383     {
384       xfree (parm->disp_name);
385       parm->disp_name = unescape_status_string (line);
386     }
387   else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen))
388     {
389       xfree (parm->disp_lang);
390       parm->disp_lang = unescape_status_string (line);
391     }
392   else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen))
393     {
394       parm->disp_sex = *line == '1'? 1 : *line == '2' ? 2: 0;
395     }
396   else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
397     {
398       xfree (parm->pubkey_url);
399       parm->pubkey_url = unescape_status_string (line);
400     }
401   else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen))
402     {
403       xfree (parm->login_data);
404       parm->login_data = unescape_status_string (line);
405     }
406   else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen))
407     {
408       parm->sig_counter = strtoul (line, NULL, 0);
409     }
410   else if (keywordlen == 10 && !memcmp (keyword, "CHV-STATUS", keywordlen))
411     {
412       char *p, *buf;
413
414       buf = p = unescape_status_string (line);
415       if (buf)
416         {
417           while (spacep (p))
418             p++;
419           parm->chv1_cached = atoi (p);
420           while (*p && !spacep (p))
421             p++;
422           while (spacep (p))
423             p++;
424           for (i=0; *p && i < 3; i++)
425             {
426               parm->chvmaxlen[i] = atoi (p);
427               while (*p && !spacep (p))
428                 p++;
429               while (spacep (p))
430                 p++;
431             }
432           for (i=0; *p && i < 3; i++)
433             {
434               parm->chvretry[i] = atoi (p);
435               while (*p && !spacep (p))
436                 p++;
437               while (spacep (p))
438                 p++;
439             }
440           xfree (buf);
441         }
442     }
443   else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
444     {
445       int no = atoi (line);
446       while (*line && !spacep (line))
447         line++;
448       while (spacep (line))
449         line++;
450       if (no == 1)
451         parm->fpr1valid = unhexify_fpr (line, parm->fpr1);
452       else if (no == 2)
453         parm->fpr2valid = unhexify_fpr (line, parm->fpr2);
454       else if (no == 3)
455         parm->fpr3valid = unhexify_fpr (line, parm->fpr3);
456     }
457   else if (keywordlen == 6 && !memcmp (keyword, "CA-FPR", keywordlen))
458     {
459       int no = atoi (line);
460       while (*line && !spacep (line))
461         line++;
462       while (spacep (line))
463         line++;
464       if (no == 1)
465         parm->cafpr1valid = unhexify_fpr (line, parm->cafpr1);
466       else if (no == 2)
467         parm->cafpr2valid = unhexify_fpr (line, parm->cafpr2);
468       else if (no == 3)
469         parm->cafpr3valid = unhexify_fpr (line, parm->cafpr3);
470     }
471   
472   return 0;
473 }
474
475 /* Call the agent to learn about a smartcard */
476 int
477 agent_learn (struct agent_card_info_s *info)
478 {
479   int rc;
480
481   rc = start_agent ();
482   if (rc)
483     return rc;
484
485   memset (info, 0, sizeof *info);
486   rc = assuan_transact (agent_ctx, "LEARN --send",
487                         NULL, NULL, NULL, NULL,
488                         learn_status_cb, info);
489   
490   return rc;
491 }
492
493 /* Call the agent to retrieve a data object.  This function returns
494    the data in the same structure as used by the learn command.  It is
495    allowed to update such a structure using this commmand. */
496 int
497 agent_scd_getattr (const char *name, struct agent_card_info_s *info)
498 {
499   int rc;
500   char line[ASSUAN_LINELENGTH];
501
502   if (!*name)
503     return gpg_error (GPG_ERR_INV_VALUE);
504
505   /* We assume that NAME does not need escaping. */
506   if (12 + strlen (name) > DIM(line)-1)
507     return gpg_error (GPG_ERR_TOO_LARGE);
508   stpcpy (stpcpy (line, "SCD GETATTR "), name); 
509
510   rc = start_agent ();
511   if (rc)
512     return rc;
513
514   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
515                         learn_status_cb, info);
516   
517   return rc;
518 }
519
520 \f
521 /* Send an setattr command to the SCdaemon.  SERIALNO is not actually
522    used here but required by gpg 1.4's implementation of this code in
523    cardglue.c. */
524 int
525 agent_scd_setattr (const char *name,
526                    const unsigned char *value, size_t valuelen,
527                    const char *serialno)
528 {
529   int rc;
530   char line[ASSUAN_LINELENGTH];
531   char *p;
532
533   if (!*name || !valuelen)
534     return gpg_error (GPG_ERR_INV_VALUE);
535
536   /* We assume that NAME does not need escaping. */
537   if (12 + strlen (name) > DIM(line)-1)
538     return gpg_error (GPG_ERR_TOO_LARGE);
539       
540   p = stpcpy (stpcpy (line, "SCD SETATTR "), name); 
541   *p++ = ' ';
542   for (; valuelen; value++, valuelen--)
543     {
544       if (p >= line + DIM(line)-5 )
545         return gpg_error (GPG_ERR_TOO_LARGE);
546       if (*value < ' ' || *value == '+' || *value == '%')
547         {
548           sprintf (p, "%%%02X", *value);
549           p += 3;
550         }
551       else if (*value == ' ')
552         *p++ = '+';
553       else
554         *p++ = *value;
555     }
556   *p = 0;
557
558   rc = start_agent ();
559   if (rc)
560     return rc;
561
562   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
563   return rc;
564 }
565
566
567 \f
568 /* Handle a KEYDATA inquiry.  Note, we only send the data,
569    assuan_transact takes care of flushing and writing the end */
570 static assuan_error_t
571 inq_writekey_parms (void *opaque, const char *keyword)
572 {
573   struct writekey_parm_s *parm = opaque; 
574
575   return assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen);
576 }
577
578
579 /* Send a WRITEKEY command to the SCdaemon. */
580 int 
581 agent_scd_writekey (int keyno, const char *serialno,
582                     const unsigned char *keydata, size_t keydatalen)
583 {
584   int rc;
585   char line[ASSUAN_LINELENGTH];
586   struct writekey_parm_s parms;
587
588   rc = start_agent ();
589   if (rc)
590     return rc;
591
592   memset (&parms, 0, sizeof parms);
593
594   snprintf (line, DIM(line)-1, "SCD WRITEKEY --force OPENPGP.%d", keyno);
595   line[DIM(line)-1] = 0;
596   parms.ctx = agent_ctx;
597   parms.keydata = keydata;
598   parms.keydatalen = keydatalen;
599   
600   rc = assuan_transact (agent_ctx, line, NULL, NULL,
601                         inq_writekey_parms, &parms, NULL, NULL);
602
603   return rc;
604 }
605
606
607
608 \f
609 /* Status callback for the SCD GENKEY command. */
610 static int
611 scd_genkey_cb (void *opaque, const char *line)
612 {
613   struct agent_card_genkey_s *parm = opaque;
614   const char *keyword = line;
615   int keywordlen;
616   gpg_error_t rc;
617
618   log_debug ("got status line `%s'\n", line);
619   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
620     ;
621   while (spacep (line))
622     line++;
623
624   if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
625     {
626       parm->fprvalid = unhexify_fpr (line, parm->fpr);
627     }
628   if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
629     {
630       gcry_mpi_t a;
631       const char *name = line;
632
633       while (*line && !spacep (line))
634         line++;
635       while (spacep (line))
636         line++;
637
638       rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, line, 0, NULL);
639       if (rc)
640         log_error ("error parsing received key data: %s\n", gpg_strerror (rc));
641       else if (*name == 'n' && spacep (name+1))
642         parm->n = a;
643       else if (*name == 'e' && spacep (name+1))
644         parm->e = a;
645       else
646         {
647           log_info ("unknown parameter name in received key data\n");
648           gcry_mpi_release (a);
649         }
650     }
651   else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
652     {
653       parm->created_at = (u32)strtoul (line, NULL, 10);
654     }
655
656   return 0;
657 }
658
659 /* Send a GENKEY command to the SCdaemon.  SERIALNO is not used in
660    this implementation. */
661 int
662 agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
663                   const char *serialno)
664 {
665   int rc;
666   char line[ASSUAN_LINELENGTH];
667
668   rc = start_agent ();
669   if (rc)
670     return rc;
671
672   memset (info, 0, sizeof *info);
673   snprintf (line, DIM(line)-1, "SCD GENKEY %s%d",
674             force? "--force ":"", keyno);
675   line[DIM(line)-1] = 0;
676
677   memset (info, 0, sizeof *info);
678   rc = assuan_transact (agent_ctx, line,
679                         NULL, NULL, NULL, NULL,
680                         scd_genkey_cb, info);
681   
682   return rc;
683 }
684
685 \f
686 static int
687 membuf_data_cb (void *opaque, const void *buffer, size_t length)
688 {
689   membuf_t *data = opaque;
690
691   if (buffer)
692     put_membuf (data, buffer, length);
693   return 0;
694 }
695   
696 /* Send a sign command to the scdaemon via gpg-agent's pass thru
697    mechanism. */
698 int
699 agent_scd_pksign (const char *serialno, int hashalgo,
700                   const unsigned char *indata, size_t indatalen,
701                   unsigned char **r_buf, size_t *r_buflen)
702 {
703   int rc, i;
704   char *p, line[ASSUAN_LINELENGTH];
705   membuf_t data;
706   size_t len;
707
708   /* Note, hashalgo is not yet used but hardwired to SHA1 in SCdaemon. */
709
710   *r_buf = NULL;
711   *r_buflen = 0;
712
713   rc = start_agent ();
714   if (rc)
715     return rc;
716
717   if (indatalen*2 + 50 > DIM(line))
718     return gpg_error (GPG_ERR_GENERAL);
719
720   sprintf (line, "SCD SETDATA ");
721   p = line + strlen (line);
722   for (i=0; i < indatalen ; i++, p += 2 )
723     sprintf (p, "%02X", indata[i]);
724   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
725   if (rc)
726     return rc;
727
728   init_membuf (&data, 1024);
729 #if 0
730   if (!hashalgo) /* Temporary test hack. */
731     snprintf (line, DIM(line)-1, "SCD PKAUTH %s", serialno);
732   else
733 #endif
734    snprintf (line, DIM(line)-1, "SCD PKSIGN %s", serialno);
735   line[DIM(line)-1] = 0;
736   rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data,
737                         NULL, NULL, NULL, NULL);
738   if (rc)
739     {
740       xfree (get_membuf (&data, &len));
741       return rc;
742     }
743   *r_buf = get_membuf (&data, r_buflen);
744
745   return 0;
746 }
747
748
749 /* Decrypt INDATA of length INDATALEN using the card identified by
750    SERIALNO.  Return the plaintext in a nwly allocated buffer stored
751    at the address of R_BUF. 
752
753    Note, we currently support only RSA or more exactly algorithms
754    taking one input data element. */
755 int
756 agent_scd_pkdecrypt (const char *serialno,
757                      const unsigned char *indata, size_t indatalen,
758                      unsigned char **r_buf, size_t *r_buflen)
759 {
760   int rc, i;
761   char *p, line[ASSUAN_LINELENGTH];
762   membuf_t data;
763   size_t len;
764
765   *r_buf = NULL;
766   rc = start_agent ();
767   if (rc)
768     return rc;
769
770   /* FIXME: use secure memory where appropriate */
771   if (indatalen*2 + 50 > DIM(line))
772     return gpg_error (GPG_ERR_GENERAL);
773
774   sprintf (line, "SCD SETDATA ");
775   p = line + strlen (line);
776   for (i=0; i < indatalen ; i++, p += 2 )
777     sprintf (p, "%02X", indata[i]);
778   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
779   if (rc)
780     return rc;
781
782   init_membuf (&data, 1024);
783   snprintf (line, DIM(line)-1, "SCD PKDECRYPT %s", serialno);
784   line[DIM(line)-1] = 0;
785   rc = assuan_transact (agent_ctx, line,
786                         membuf_data_cb, &data,
787                         NULL, NULL, NULL, NULL);
788   if (rc)
789     {
790       xfree (get_membuf (&data, &len));
791       return rc;
792     }
793   *r_buf = get_membuf (&data, r_buflen);
794   if (!*r_buf)
795     return gpg_error (GPG_ERR_ENOMEM);
796
797   return 0;
798 }
799
800
801 /* Change the PIN of an OpenPGP card or reset the retry counter.
802    CHVNO 1: Change the PIN
803          2: Same as 1
804          3: Change the admin PIN
805        101: Set a new PIN and reset the retry counter
806        102: Same as 101
807    SERIALNO is not used.
808  */
809 int
810 agent_scd_change_pin (int chvno, const char *serialno)
811 {
812   int rc;
813   char line[ASSUAN_LINELENGTH];
814   const char *reset = "";
815
816   if (chvno >= 100)
817     reset = "--reset";
818   chvno %= 100;
819
820   rc = start_agent ();
821   if (rc)
822     return rc;
823
824   snprintf (line, DIM(line)-1, "SCD PASSWD %s %d", reset, chvno);
825   line[DIM(line)-1] = 0;
826   rc = assuan_transact (agent_ctx, line, NULL, NULL,
827                         NULL, NULL, NULL, NULL);
828   return rc;
829 }
830
831
832 /* Perform a CHECKPIN operation.  SERIALNO should be the serial
833    number of the card - optionally followed by the fingerprint;
834    however the fingerprint is ignored here. */
835 int
836 agent_scd_checkpin  (const char *serialno)
837 {
838   int rc;
839   char line[ASSUAN_LINELENGTH];
840
841   rc = start_agent ();
842   if (rc)
843     return rc;
844
845   snprintf (line, DIM(line)-1, "SCD CHECKPIN %s", serialno);
846   line[DIM(line)-1] = 0;
847   return assuan_transact (agent_ctx, line,
848                           NULL, NULL,
849                           NULL, NULL, NULL, NULL);
850 }
851
852
853 /* Dummy function, only used by the gpg 1.4 implementation. */
854 void
855 agent_clear_pin_cache (const char *sn)
856 {
857
858 }