fc81e2fa38c93ed1a4d2e22965759f134be4004b
[gnupg.git] / agent / call-scd.c
1 /* call-scd.c - fork of the scdaemon to do SC operations
2  *      Copyright (C) 2001, 2002, 2005 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <assert.h>
28 #include <unistd.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 #ifndef HAVE_W32_SYSTEM
32 #include <sys/wait.h>
33 #endif
34 #include <pth.h>
35
36 #include "agent.h"
37 #include <assuan.h>
38
39 #ifdef _POSIX_OPEN_MAX
40 #define MAX_OPEN_FDS _POSIX_OPEN_MAX
41 #else
42 #define MAX_OPEN_FDS 20
43 #endif
44
45 /* Definition of module local data of the CTRL structure.  */
46 struct scd_local_s
47 {
48   assuan_context_t ctx; /* NULL or session context for the SCdaemon
49                            used with this connection. */
50   int locked;           /* This flag is used to assert proper use of
51                            start_scd and unlock_scd. */
52
53 };
54
55
56 /* Callback parameter for learn card */
57 struct learn_parm_s
58 {
59   void (*kpinfo_cb)(void*, const char *);
60   void *kpinfo_cb_arg;
61   void (*certinfo_cb)(void*, const char *);
62   void *certinfo_cb_arg;
63   void (*sinfo_cb)(void*, const char *, size_t, const char *);
64   void *sinfo_cb_arg;
65 };
66
67 struct inq_needpin_s 
68 {
69   assuan_context_t ctx;
70   int (*getpin_cb)(void *, const char *, char*, size_t);
71   void *getpin_cb_arg;
72 };
73
74
75 /* A Mutex used inside the start_scd function. */
76 static pth_mutex_t start_scd_lock;
77
78 /* A malloced string with the name of the socket to be used for
79    additional connections.  May be NULL if not provided by
80    SCdaemon. */
81 static char *socket_name;
82
83 /* The context of the primary connection.  This is also used as a flag
84    to indicate whether the scdaemon has been started. */
85 static assuan_context_t primary_scd_ctx;
86
87 /* To allow reuse of the primary connection, the following flag is set
88    to true if the primary context has been reset and is not in use by
89    any connection. */
90 static int primary_scd_ctx_reusable;
91
92
93
94 /* Local prototypes.  */
95 static assuan_error_t membuf_data_cb (void *opaque,
96                                       const void *buffer, size_t length);
97
98
99
100 \f
101 /* This function must be called once to initialize this module.  This
102    has to be done before a second thread is spawned.  We can't do the
103    static initialization because Pth emulation code might not be able
104    to do a static init; in particular, it is not possible for W32. */
105 void
106 initialize_module_call_scd (void)
107 {
108   static int initialized;
109
110   if (!initialized)
111     {
112       if (!pth_mutex_init (&start_scd_lock))
113         log_fatal ("error initializing mutex: %s\n", strerror (errno));
114       initialized = 1;
115     }
116 }
117
118
119 /* The unlock_scd function shall be called after having accessed the
120    SCD.  It is currently not very useful but gives an opportunity to
121    keep track of connections currently calling SCD.  Note that the
122    "lock" operation is done by the start_scd() function which must be
123    called and error checked before any SCD operation.  CTRL is the
124    usual connection context and RC the error code to be passed trhough
125    the function. */
126 static int 
127 unlock_scd (ctrl_t ctrl, int rc)
128 {
129   if (ctrl->scd_local->locked != 1)
130     {
131       log_error ("unlock_scd: invalid lock count (%d)\n",
132                  ctrl->scd_local->locked);
133       if (!rc)
134         rc = gpg_error (GPG_ERR_INTERNAL);
135     }
136   ctrl->scd_local->locked = 0;
137   return rc;
138 }
139
140 /* To make sure we leave no secrets in our image after forking of the
141    scdaemon, we use this callback. */
142 static void
143 atfork_cb (void *opaque, int where)
144 {
145   if (!where)
146     gcry_control (GCRYCTL_TERM_SECMEM);
147 }
148
149
150 /* Fork off the SCdaemon if this has not already been done.  Lock the
151    daemon and make sure that a proper context has been setup in CTRL.
152    Thsi fucntion might also lock the daemon, which means that the
153    caller must call unlock_scd after this fucntion has returned
154    success and the actual Assuan transaction been done. */
155 static int
156 start_scd (ctrl_t ctrl)
157 {
158   gpg_error_t err = 0;
159   const char *pgmname;
160   assuan_context_t ctx;
161   const char *argv[3];
162   int no_close_list[3];
163   int i;
164   int rc;
165
166   if (opt.disable_scdaemon)
167     return gpg_error (GPG_ERR_NOT_SUPPORTED);
168
169   /* If this is the first call for this session, setup the local data
170      structure. */
171   if (!ctrl->scd_local)
172     {
173       ctrl->scd_local = xtrycalloc (1, sizeof *ctrl->scd_local);
174       if (!ctrl->scd_local)
175         return gpg_error_from_errno (errno);
176     }
177
178
179   /* Assert that the lock count is as expected. */
180   if (ctrl->scd_local->locked)
181     {
182       log_error ("start_scd: invalid lock count (%d)\n",
183                  ctrl->scd_local->locked);
184       return gpg_error (GPG_ERR_INTERNAL);
185     }
186   ctrl->scd_local->locked++;
187
188   /* If we already have a context, we better do a sanity check now to
189      see whether it has accidently died.  This avoids annoying
190      timeouts and hung connections. */
191   if (ctrl->scd_local->ctx)
192     {
193       pid_t pid;
194 #ifndef HAVE_W32_SYSTEM 
195       pid = assuan_get_pid (ctrl->scd_local->ctx);
196       if (pid != (pid_t)(-1) && pid
197           && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
198         {
199           assuan_disconnect (ctrl->scd_local->ctx);
200           ctrl->scd_local->ctx = NULL;
201         }
202       else
203 #endif
204         return 0; /* Okay, the context is fine. */
205     }
206
207   /* We need to protect the lowwing code. */
208   if (!pth_mutex_acquire (&start_scd_lock, 0, NULL))
209     {
210       log_error ("failed to acquire the start_scd lock: %s\n",
211                  strerror (errno));
212       return gpg_error (GPG_ERR_INTERNAL);
213     }
214
215   /* Check whether the pipe server has already been started and in
216      this case either reuse a lingering pipe connection or establish a
217      new socket based one. */
218   if (primary_scd_ctx && primary_scd_ctx_reusable)
219     {
220       ctx = primary_scd_ctx;
221       primary_scd_ctx_reusable = 0;
222       if (opt.verbose)
223         log_info ("new connection to SCdaemon established (reusing)\n");
224       goto leave;
225     }
226
227   if (socket_name)
228     {
229       rc = assuan_socket_connect (&ctx, socket_name, 0);
230       if (rc)
231         {
232           log_error ("can't connect to socket `%s': %s\n",
233                      socket_name, assuan_strerror (rc));
234           err = gpg_error (GPG_ERR_NO_SCDAEMON);
235           goto leave;
236         }
237
238       if (opt.verbose)
239         log_info ("new connection to SCdaemon established\n");
240       goto leave;
241     }
242
243   if (primary_scd_ctx)
244     {
245       log_info ("SCdaemon is running but won't accept further connections\n");
246       err = gpg_error (GPG_ERR_NO_SCDAEMON);
247       goto leave;
248     }
249
250   /* Nope, it has not been started.  Fire it up now. */
251   if (opt.verbose)
252     log_info ("no running SCdaemon - starting it\n");
253       
254   if (fflush (NULL))
255     {
256       err = gpg_error (gpg_err_code_from_errno (errno));
257       log_error ("error flushing pending output: %s\n", strerror (errno));
258       goto leave;
259     }
260
261   if (!opt.scdaemon_program || !*opt.scdaemon_program)
262     opt.scdaemon_program = GNUPG_DEFAULT_SCDAEMON;
263   if ( !(pgmname = strrchr (opt.scdaemon_program, '/')))
264     pgmname = opt.scdaemon_program;
265   else
266     pgmname++;
267
268   argv[0] = pgmname;
269   argv[1] = "--multi-server";
270   argv[2] = NULL;
271
272   i=0;
273   if (!opt.running_detached)
274     {
275       if (log_get_fd () != -1)
276         no_close_list[i++] = log_get_fd ();
277       no_close_list[i++] = fileno (stderr);
278     }
279   no_close_list[i] = -1;
280
281   /* Connect to the pinentry and perform initial handshaking */
282   rc = assuan_pipe_connect2 (&ctx, opt.scdaemon_program, (char**)argv,
283                              no_close_list, atfork_cb, NULL);
284   if (rc)
285     {
286       log_error ("can't connect to the SCdaemon: %s\n",
287                  assuan_strerror (rc));
288       err = gpg_error (GPG_ERR_NO_SCDAEMON);
289       goto leave;
290     }
291
292   if (opt.verbose)
293     log_debug ("first connection to SCdaemon established\n");
294
295   /* Get the name of the additional socket opened by scdaemon. */
296   {
297     membuf_t data;
298     unsigned char *databuf;
299     size_t datalen;
300
301     xfree (socket_name);
302     socket_name = NULL;
303     init_membuf (&data, 256);
304     assuan_transact (ctx, "GETINFO socket_name",
305                      membuf_data_cb, &data, NULL, NULL, NULL, NULL);
306
307     databuf = get_membuf (&data, &datalen);
308     if (databuf && datalen)
309       {
310         socket_name = xtrymalloc (datalen + 1);
311         if (!socket_name)
312           log_error ("warning: can't store socket name: %s\n",
313                      strerror (errno));
314         else
315           {
316             memcpy (socket_name, databuf, datalen);
317             socket_name[datalen] = 0;
318             if (DBG_ASSUAN)
319               log_debug ("additional connections at `%s'\n", socket_name);
320           }
321       }
322     xfree (databuf);
323   }
324
325   /* Tell the scdaemon we want him to send us an event signal. */
326 #ifndef HAVE_W32_SYSTEM
327   {
328     char buf[100];
329
330     sprintf (buf, "OPTION event-signal=%d", SIGUSR2);
331     assuan_transact (ctx, buf, NULL, NULL, NULL, NULL, NULL, NULL);
332   }
333 #endif
334
335   primary_scd_ctx = ctx;
336   primary_scd_ctx_reusable = 0;
337
338  leave:
339   if (err)
340     {
341       unlock_scd (ctrl, err);
342     } 
343   else
344     {
345       ctrl->scd_local->ctx = ctx;
346     }
347   if (!pth_mutex_release (&start_scd_lock))
348     log_error ("failed to release the start_scd lock: %s\n", strerror (errno));
349   return err;
350 }
351
352
353
354 /* Reset the SCD if it has been used. */
355 int
356 agent_reset_scd (ctrl_t ctrl)
357 {
358   if (ctrl->scd_local)
359     {
360       if (ctrl->scd_local->ctx)
361         {
362           /* We can't disconnect the primary context becuase libassuan
363              does a waitpid on it and thus the system would hang.
364              Instead we send a reset and keep that connection for
365              reuse. */
366           if (ctrl->scd_local->ctx == primary_scd_ctx)
367             {
368               if (!assuan_transact (primary_scd_ctx, "RESET",
369                                     NULL, NULL, NULL, NULL, NULL, NULL))
370                 primary_scd_ctx_reusable = 1;
371             }
372           else
373             assuan_disconnect (ctrl->scd_local->ctx);
374         }
375       xfree (ctrl->scd_local);
376       ctrl->scd_local = NULL;
377     }
378
379   return 0;
380 }
381
382
383 \f
384 /* Return a new malloced string by unescaping the string S.  Escaping
385    is percent escaping and '+'/space mapping.  A binary Nul will
386    silently be replaced by a 0xFF.  Function returns NULL to indicate
387    an out of memory status. */
388 static char *
389 unescape_status_string (const unsigned char *s)
390 {
391   char *buffer, *d;
392
393   buffer = d = xtrymalloc (strlen (s)+1);
394   if (!buffer)
395     return NULL;
396   while (*s)
397     {
398       if (*s == '%' && s[1] && s[2])
399         { 
400           s++;
401           *d = xtoi_2 (s);
402           if (!*d)
403             *d = '\xff';
404           d++;
405           s += 2;
406         }
407       else if (*s == '+')
408         {
409           *d++ = ' ';
410           s++;
411         }
412       else
413         *d++ = *s++;
414     }
415   *d = 0; 
416   return buffer;
417 }
418
419
420 \f
421 static AssuanError
422 learn_status_cb (void *opaque, const char *line)
423 {
424   struct learn_parm_s *parm = opaque;
425   const char *keyword = line;
426   int keywordlen;
427
428   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
429     ;
430   while (spacep (line))
431     line++;
432   if (keywordlen == 8 && !memcmp (keyword, "CERTINFO", keywordlen))
433     {
434       parm->certinfo_cb (parm->certinfo_cb_arg, line);
435     }
436   else if (keywordlen == 11 && !memcmp (keyword, "KEYPAIRINFO", keywordlen))
437     {
438       parm->kpinfo_cb (parm->kpinfo_cb_arg, line);
439     }
440   else if (keywordlen && *line)
441     {
442       parm->sinfo_cb (parm->sinfo_cb_arg, keyword, keywordlen, line);
443     }
444   
445   return 0;
446 }
447
448 /* Perform the LEARN command and return a list of all private keys
449    stored on the card. */
450 int
451 agent_card_learn (ctrl_t ctrl,
452                   void (*kpinfo_cb)(void*, const char *),
453                   void *kpinfo_cb_arg,
454                   void (*certinfo_cb)(void*, const char *),
455                   void *certinfo_cb_arg,
456                   void (*sinfo_cb)(void*, const char *, size_t, const char *),
457                   void *sinfo_cb_arg)
458 {
459   int rc;
460   struct learn_parm_s parm;
461
462   rc = start_scd (ctrl);
463   if (rc)
464     return rc;
465
466   memset (&parm, 0, sizeof parm);
467   parm.kpinfo_cb = kpinfo_cb;
468   parm.kpinfo_cb_arg = kpinfo_cb_arg;
469   parm.certinfo_cb = certinfo_cb;
470   parm.certinfo_cb_arg = certinfo_cb_arg;
471   parm.sinfo_cb = sinfo_cb;
472   parm.sinfo_cb_arg = sinfo_cb_arg;
473   rc = assuan_transact (ctrl->scd_local->ctx, "LEARN --force",
474                         NULL, NULL, NULL, NULL,
475                         learn_status_cb, &parm);
476   if (rc)
477     return unlock_scd (ctrl, map_assuan_err (rc));
478
479   return unlock_scd (ctrl, 0);
480 }
481
482
483 \f
484 static AssuanError
485 get_serialno_cb (void *opaque, const char *line)
486 {
487   char **serialno = opaque;
488   const char *keyword = line;
489   const char *s;
490   int keywordlen, n;
491
492   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
493     ;
494   while (spacep (line))
495     line++;
496
497   if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
498     {
499       if (*serialno)
500         return ASSUAN_Unexpected_Status;
501       for (n=0,s=line; hexdigitp (s); s++, n++)
502         ;
503       if (!n || (n&1)|| !(spacep (s) || !*s) )
504         return ASSUAN_Invalid_Status;
505       *serialno = xtrymalloc (n+1);
506       if (!*serialno)
507         return ASSUAN_Out_Of_Core;
508       memcpy (*serialno, line, n);
509       (*serialno)[n] = 0;
510     }
511   
512   return 0;
513 }
514
515 /* Return the serial number of the card or an appropriate error.  The
516    serial number is returned as a hexstring. */
517 int
518 agent_card_serialno (ctrl_t ctrl, char **r_serialno)
519 {
520   int rc;
521   char *serialno = NULL;
522
523   rc = start_scd (ctrl);
524   if (rc)
525     return rc;
526
527   rc = assuan_transact (ctrl->scd_local->ctx, "SERIALNO",
528                         NULL, NULL, NULL, NULL,
529                         get_serialno_cb, &serialno);
530   if (rc)
531     {
532       xfree (serialno);
533       return unlock_scd (ctrl, map_assuan_err (rc));
534     }
535   *r_serialno = serialno;
536   return unlock_scd (ctrl, 0);
537 }
538
539
540
541 \f
542 static AssuanError
543 membuf_data_cb (void *opaque, const void *buffer, size_t length)
544 {
545   membuf_t *data = opaque;
546
547   if (buffer)
548     put_membuf (data, buffer, length);
549   return 0;
550 }
551   
552 /* Handle the NEEDPIN inquiry. */
553 static AssuanError
554 inq_needpin (void *opaque, const char *line)
555 {
556   struct inq_needpin_s *parm = opaque;
557   char *pin;
558   size_t pinlen;
559   int rc;
560
561   if (!(!strncmp (line, "NEEDPIN", 7) && (line[7] == ' ' || !line[7])))
562     {
563       log_error ("unsupported inquiry `%s'\n", line);
564       return ASSUAN_Inquire_Unknown;
565     }
566   line += 7;
567
568   pinlen = 90;
569   pin = gcry_malloc_secure (pinlen);
570   if (!pin)
571     return ASSUAN_Out_Of_Core;
572
573   rc = parm->getpin_cb (parm->getpin_cb_arg, line, pin, pinlen);
574   if (rc)
575     rc = ASSUAN_Canceled;
576   if (!rc)
577     rc = assuan_send_data (parm->ctx, pin, pinlen);
578   xfree (pin);
579
580   return rc;
581 }
582
583
584
585 /* Create a signature using the current card */
586 int
587 agent_card_pksign (ctrl_t ctrl,
588                    const char *keyid,
589                    int (*getpin_cb)(void *, const char *, char*, size_t),
590                    void *getpin_cb_arg,
591                    const unsigned char *indata, size_t indatalen,
592                    char **r_buf, size_t *r_buflen)
593 {
594   int rc, i;
595   char *p, line[ASSUAN_LINELENGTH];
596   membuf_t data;
597   struct inq_needpin_s inqparm;
598   size_t len;
599   unsigned char *sigbuf;
600   size_t sigbuflen;
601
602   *r_buf = NULL;
603   rc = start_scd (ctrl);
604   if (rc)
605     return rc;
606
607   if (indatalen*2 + 50 > DIM(line))
608     return unlock_scd (ctrl, gpg_error (GPG_ERR_GENERAL));
609
610   sprintf (line, "SETDATA ");
611   p = line + strlen (line);
612   for (i=0; i < indatalen ; i++, p += 2 )
613     sprintf (p, "%02X", indata[i]);
614   rc = assuan_transact (ctrl->scd_local->ctx, line,
615                         NULL, NULL, NULL, NULL, NULL, NULL);
616   if (rc)
617     return unlock_scd (ctrl, map_assuan_err (rc));
618
619   init_membuf (&data, 1024);
620   inqparm.ctx = ctrl->scd_local->ctx;
621   inqparm.getpin_cb = getpin_cb;
622   inqparm.getpin_cb_arg = getpin_cb_arg;
623   snprintf (line, DIM(line)-1, 
624             ctrl->use_auth_call? "PKAUTH %s":"PKSIGN %s", keyid);
625   line[DIM(line)-1] = 0;
626   rc = assuan_transact (ctrl->scd_local->ctx, line,
627                         membuf_data_cb, &data,
628                         inq_needpin, &inqparm,
629                         NULL, NULL);
630   if (rc)
631     {
632       xfree (get_membuf (&data, &len));
633       return unlock_scd (ctrl, map_assuan_err (rc));
634     }
635   sigbuf = get_membuf (&data, &sigbuflen);
636
637   /* Create an S-expression from it which is formatted like this:
638      "(7:sig-val(3:rsa(1:sSIGBUFLEN:SIGBUF)))" */
639   *r_buflen = 21 + 11 + sigbuflen + 4;
640   *r_buf = xtrymalloc (*r_buflen);
641   if (!*r_buf)
642     {
643       gpg_error_t tmperr = out_of_core ();
644       xfree (*r_buf);
645       return unlock_scd (ctrl, tmperr);
646     }
647   p = stpcpy (*r_buf, "(7:sig-val(3:rsa(1:s" );
648   sprintf (p, "%u:", (unsigned int)sigbuflen);
649   p += strlen (p);
650   memcpy (p, sigbuf, sigbuflen);
651   p += sigbuflen;
652   strcpy (p, ")))");
653   xfree (sigbuf);
654
655   assert (gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL));
656   return unlock_scd (ctrl, 0);
657 }
658
659 /* Decipher INDATA using the current card. Note that the returned value is */
660 int
661 agent_card_pkdecrypt (ctrl_t ctrl,
662                       const char *keyid,
663                       int (*getpin_cb)(void *, const char *, char*, size_t),
664                       void *getpin_cb_arg,
665                       const unsigned char *indata, size_t indatalen,
666                       char **r_buf, size_t *r_buflen)
667 {
668   int rc, i;
669   char *p, line[ASSUAN_LINELENGTH];
670   membuf_t data;
671   struct inq_needpin_s inqparm;
672   size_t len;
673
674   *r_buf = NULL;
675   rc = start_scd (ctrl);
676   if (rc)
677     return rc;
678
679   /* FIXME: use secure memory where appropriate */
680   if (indatalen*2 + 50 > DIM(line))
681     return unlock_scd (ctrl, gpg_error (GPG_ERR_GENERAL));
682
683   sprintf (line, "SETDATA ");
684   p = line + strlen (line);
685   for (i=0; i < indatalen ; i++, p += 2 )
686     sprintf (p, "%02X", indata[i]);
687   rc = assuan_transact (ctrl->scd_local->ctx, line,
688                         NULL, NULL, NULL, NULL, NULL, NULL);
689   if (rc)
690     return unlock_scd (ctrl, map_assuan_err (rc));
691
692   init_membuf (&data, 1024);
693   inqparm.ctx = ctrl->scd_local->ctx;
694   inqparm.getpin_cb = getpin_cb;
695   inqparm.getpin_cb_arg = getpin_cb_arg;
696   snprintf (line, DIM(line)-1, "PKDECRYPT %s", keyid);
697   line[DIM(line)-1] = 0;
698   rc = assuan_transact (ctrl->scd_local->ctx, line,
699                         membuf_data_cb, &data,
700                         inq_needpin, &inqparm,
701                         NULL, NULL);
702   if (rc)
703     {
704       xfree (get_membuf (&data, &len));
705       return unlock_scd (ctrl, map_assuan_err (rc));
706     }
707   *r_buf = get_membuf (&data, r_buflen);
708   if (!*r_buf)
709     return unlock_scd (ctrl, gpg_error (GPG_ERR_ENOMEM));
710
711   return unlock_scd (ctrl, 0);
712 }
713
714
715 \f
716 /* Read a certificate with ID into R_BUF and R_BUFLEN. */
717 int
718 agent_card_readcert (ctrl_t ctrl,
719                      const char *id, char **r_buf, size_t *r_buflen)
720 {
721   int rc;
722   char line[ASSUAN_LINELENGTH];
723   membuf_t data;
724   size_t len;
725
726   *r_buf = NULL;
727   rc = start_scd (ctrl);
728   if (rc)
729     return rc;
730
731   init_membuf (&data, 1024);
732   snprintf (line, DIM(line)-1, "READCERT %s", id);
733   line[DIM(line)-1] = 0;
734   rc = assuan_transact (ctrl->scd_local->ctx, line,
735                         membuf_data_cb, &data,
736                         NULL, NULL,
737                         NULL, NULL);
738   if (rc)
739     {
740       xfree (get_membuf (&data, &len));
741       return unlock_scd (ctrl, map_assuan_err (rc));
742     }
743   *r_buf = get_membuf (&data, r_buflen);
744   if (!*r_buf)
745     return unlock_scd (ctrl, gpg_error (GPG_ERR_ENOMEM));
746
747   return unlock_scd (ctrl, 0);
748 }
749
750
751 \f
752 /* Read a key with ID and return it in an allocate buffer pointed to
753    by r_BUF as a valid S-expression. */
754 int
755 agent_card_readkey (ctrl_t ctrl, const char *id, unsigned char **r_buf)
756 {
757   int rc;
758   char line[ASSUAN_LINELENGTH];
759   membuf_t data;
760   size_t len, buflen;
761
762   *r_buf = NULL;
763   rc = start_scd (ctrl);
764   if (rc)
765     return rc;
766
767   init_membuf (&data, 1024);
768   snprintf (line, DIM(line)-1, "READKEY %s", id);
769   line[DIM(line)-1] = 0;
770   rc = assuan_transact (ctrl->scd_local->ctx, line,
771                         membuf_data_cb, &data,
772                         NULL, NULL,
773                         NULL, NULL);
774   if (rc)
775     {
776       xfree (get_membuf (&data, &len));
777       return unlock_scd (ctrl, map_assuan_err (rc));
778     }
779   *r_buf = get_membuf (&data, &buflen);
780   if (!*r_buf)
781     return unlock_scd (ctrl, gpg_error (GPG_ERR_ENOMEM));
782
783   if (!gcry_sexp_canon_len (*r_buf, buflen, NULL, NULL))
784     {
785       xfree (*r_buf); *r_buf = NULL;
786       return unlock_scd (ctrl, gpg_error (GPG_ERR_INV_VALUE));
787     }
788
789   return unlock_scd (ctrl, 0);
790 }
791
792
793 \f
794 /* Type used with the card_getattr_cb.  */
795 struct card_getattr_parm_s {
796   const char *keyword;  /* Keyword to look for.  */
797   size_t keywordlen;    /* strlen of KEYWORD.  */
798   char *data;           /* Malloced and unescaped data.  */
799   int error;            /* ERRNO value or 0 on success. */
800 };
801
802 /* Callback function for agent_card_getattr.  */
803 static assuan_error_t
804 card_getattr_cb (void *opaque, const char *line)
805 {
806   struct card_getattr_parm_s *parm = opaque;
807   const char *keyword = line;
808   int keywordlen;
809
810   if (parm->data)
811     return 0; /* We want only the first occurrence.  */
812
813   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
814     ;
815   while (spacep (line))
816     line++;
817
818   if (keywordlen == parm->keywordlen
819       && !memcmp (keyword, parm->keyword, keywordlen))
820     {
821       parm->data = unescape_status_string (line);
822       if (!parm->data)
823         parm->error = errno;
824     }
825   
826   return 0;
827 }
828
829
830 /* Call the agent to retrieve a single line data object. On success
831    the object is malloced and stored at RESULT; it is guaranteed that
832    NULL is never stored in this case.  On error an error code is
833    returned and NULL stored at RESULT. */
834 gpg_error_t
835 agent_card_getattr (ctrl_t ctrl, const char *name, char **result)
836 {
837   int err;
838   struct card_getattr_parm_s parm;
839   char line[ASSUAN_LINELENGTH];
840
841   *result = NULL;
842
843   if (!*name)
844     return gpg_error (GPG_ERR_INV_VALUE);
845
846   memset (&parm, 0, sizeof parm);
847   parm.keyword = name;
848   parm.keywordlen = strlen (name);
849
850   /* We assume that NAME does not need escaping. */
851   if (8 + strlen (name) > DIM(line)-1)
852     return gpg_error (GPG_ERR_TOO_LARGE);
853   stpcpy (stpcpy (line, "GETATTR "), name); 
854
855   err = start_scd (ctrl);
856   if (err)
857     return err;
858
859   err = map_assuan_err (assuan_transact (ctrl->scd_local->ctx, line,
860                                          NULL, NULL, NULL, NULL,
861                                          card_getattr_cb, &parm));
862   if (!err && parm.error)
863     err = gpg_error_from_errno (parm.error);
864   
865   if (!err && !parm.data)
866     err = gpg_error (GPG_ERR_NO_DATA);
867   
868   if (!err)
869     *result = parm.data;
870   else
871     xfree (parm.data);
872
873   return unlock_scd (ctrl, err);
874 }
875
876
877
878 \f
879 static AssuanError
880 pass_status_thru (void *opaque, const char *line)
881 {
882   ASSUAN_CONTEXT ctx = opaque;
883   char keyword[200];
884   int i;
885
886   for (i=0; *line && !spacep (line) && i < DIM(keyword)-1; line++, i++)
887     keyword[i] = *line;
888   keyword[i] = 0;
889   /* truncate any remaining keyword stuff. */
890   for (; *line && !spacep (line); line++)
891     ;
892   while (spacep (line))
893     line++;
894
895   assuan_write_status (ctx, keyword, line);
896   return 0;
897 }
898
899 static AssuanError
900 pass_data_thru (void *opaque, const void *buffer, size_t length)
901 {
902   ASSUAN_CONTEXT ctx = opaque;
903
904   assuan_send_data (ctx, buffer, length);
905   return 0;
906 }
907
908
909 /* Send the line CMDLINE with command for the SCDdaemon to it and send
910    all status messages back.  This command is used as a general quoting
911    mechanism to pass everything verbatim to SCDAEMOPN.  The PIN
912    inquirey is handled inside gpg-agent. */
913 int
914 agent_card_scd (ctrl_t ctrl, const char *cmdline,
915                 int (*getpin_cb)(void *, const char *, char*, size_t),
916                 void *getpin_cb_arg, void *assuan_context)
917 {
918   int rc;
919   struct inq_needpin_s inqparm;
920
921   rc = start_scd (ctrl);
922   if (rc)
923     return rc;
924
925   inqparm.ctx = ctrl->scd_local->ctx;
926   inqparm.getpin_cb = getpin_cb;
927   inqparm.getpin_cb_arg = getpin_cb_arg;
928   rc = assuan_transact (ctrl->scd_local->ctx, cmdline,
929                         pass_data_thru, assuan_context,
930                         inq_needpin, &inqparm,
931                         pass_status_thru, assuan_context);
932   if (rc)
933     {
934       return unlock_scd (ctrl, map_assuan_err (rc));
935     }
936
937   return unlock_scd (ctrl, 0);
938 }
939
940