Changed the scdaemon to handle concurrent sessions. Adjusted
[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[4];
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] = "--server";
270   argv[2] = "--multi-server";
271   argv[3] = NULL;
272
273   i=0;
274   if (!opt.running_detached)
275     {
276       if (log_get_fd () != -1)
277         no_close_list[i++] = log_get_fd ();
278       no_close_list[i++] = fileno (stderr);
279     }
280   no_close_list[i] = -1;
281
282   /* Connect to the pinentry and perform initial handshaking */
283   rc = assuan_pipe_connect2 (&ctx, opt.scdaemon_program, (char**)argv,
284                              no_close_list, atfork_cb, NULL);
285   if (rc)
286     {
287       log_error ("can't connect to the SCdaemon: %s\n",
288                  assuan_strerror (rc));
289       err = gpg_error (GPG_ERR_NO_SCDAEMON);
290       goto leave;
291     }
292
293   if (opt.verbose)
294     log_debug ("first connection to SCdaemon established\n");
295
296   /* Get the name of the additional socket opened by scdaemon. */
297   {
298     membuf_t data;
299     unsigned char *databuf;
300     size_t datalen;
301
302     xfree (socket_name);
303     socket_name = NULL;
304     init_membuf (&data, 256);
305     assuan_transact (ctx, "GETINFO socket_name",
306                      membuf_data_cb, &data, NULL, NULL, NULL, NULL);
307
308     databuf = get_membuf (&data, &datalen);
309     if (databuf && datalen)
310       {
311         socket_name = xtrymalloc (datalen + 1);
312         if (!socket_name)
313           log_error ("warning: can't store socket name: %s\n",
314                      strerror (errno));
315         else
316           {
317             memcpy (socket_name, databuf, datalen);
318             socket_name[datalen] = 0;
319             if (DBG_ASSUAN)
320               log_debug ("additional connections at `%s'\n", socket_name);
321           }
322       }
323     xfree (databuf);
324   }
325
326   /* Tell the scdaemon we want him to send us an event signal. */
327 #ifndef HAVE_W32_SYSTEM
328   {
329     char buf[100];
330
331     sprintf (buf, "OPTION event-signal=%d", SIGUSR2);
332     assuan_transact (ctx, buf, NULL, NULL, NULL, NULL, NULL, NULL);
333   }
334 #endif
335
336   primary_scd_ctx = ctx;
337   primary_scd_ctx_reusable = 0;
338
339  leave:
340   if (err)
341     {
342       unlock_scd (ctrl, err);
343     } 
344   else
345     {
346       ctrl->scd_local->ctx = ctx;
347     }
348   if (!pth_mutex_release (&start_scd_lock))
349     log_error ("failed to release the start_scd lock: %s\n", strerror (errno));
350   return err;
351 }
352
353
354
355 /* Reset the SCD if it has been used. */
356 int
357 agent_reset_scd (ctrl_t ctrl)
358 {
359   if (ctrl->scd_local)
360     {
361       if (ctrl->scd_local->ctx)
362         {
363           /* We can't disconnect the primary context becuase libassuan
364              does a waitpid on it and thus the system would hang.
365              Instead we send a reset and keep that connection for
366              reuse. */
367           if (ctrl->scd_local->ctx == primary_scd_ctx)
368             {
369               if (!assuan_transact (primary_scd_ctx, "RESET",
370                                     NULL, NULL, NULL, NULL, NULL, NULL))
371                 primary_scd_ctx_reusable = 1;
372             }
373           else
374             assuan_disconnect (ctrl->scd_local->ctx);
375         }
376       xfree (ctrl->scd_local);
377       ctrl->scd_local = NULL;
378     }
379
380   return 0;
381 }
382
383
384 \f
385 /* Return a new malloced string by unescaping the string S.  Escaping
386    is percent escaping and '+'/space mapping.  A binary Nul will
387    silently be replaced by a 0xFF.  Function returns NULL to indicate
388    an out of memory status. */
389 static char *
390 unescape_status_string (const unsigned char *s)
391 {
392   char *buffer, *d;
393
394   buffer = d = xtrymalloc (strlen (s)+1);
395   if (!buffer)
396     return NULL;
397   while (*s)
398     {
399       if (*s == '%' && s[1] && s[2])
400         { 
401           s++;
402           *d = xtoi_2 (s);
403           if (!*d)
404             *d = '\xff';
405           d++;
406           s += 2;
407         }
408       else if (*s == '+')
409         {
410           *d++ = ' ';
411           s++;
412         }
413       else
414         *d++ = *s++;
415     }
416   *d = 0; 
417   return buffer;
418 }
419
420
421 \f
422 static AssuanError
423 learn_status_cb (void *opaque, const char *line)
424 {
425   struct learn_parm_s *parm = opaque;
426   const char *keyword = line;
427   int keywordlen;
428
429   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
430     ;
431   while (spacep (line))
432     line++;
433   if (keywordlen == 8 && !memcmp (keyword, "CERTINFO", keywordlen))
434     {
435       parm->certinfo_cb (parm->certinfo_cb_arg, line);
436     }
437   else if (keywordlen == 11 && !memcmp (keyword, "KEYPAIRINFO", keywordlen))
438     {
439       parm->kpinfo_cb (parm->kpinfo_cb_arg, line);
440     }
441   else if (keywordlen && *line)
442     {
443       parm->sinfo_cb (parm->sinfo_cb_arg, keyword, keywordlen, line);
444     }
445   
446   return 0;
447 }
448
449 /* Perform the LEARN command and return a list of all private keys
450    stored on the card. */
451 int
452 agent_card_learn (ctrl_t ctrl,
453                   void (*kpinfo_cb)(void*, const char *),
454                   void *kpinfo_cb_arg,
455                   void (*certinfo_cb)(void*, const char *),
456                   void *certinfo_cb_arg,
457                   void (*sinfo_cb)(void*, const char *, size_t, const char *),
458                   void *sinfo_cb_arg)
459 {
460   int rc;
461   struct learn_parm_s parm;
462
463   rc = start_scd (ctrl);
464   if (rc)
465     return rc;
466
467   memset (&parm, 0, sizeof parm);
468   parm.kpinfo_cb = kpinfo_cb;
469   parm.kpinfo_cb_arg = kpinfo_cb_arg;
470   parm.certinfo_cb = certinfo_cb;
471   parm.certinfo_cb_arg = certinfo_cb_arg;
472   parm.sinfo_cb = sinfo_cb;
473   parm.sinfo_cb_arg = sinfo_cb_arg;
474   rc = assuan_transact (ctrl->scd_local->ctx, "LEARN --force",
475                         NULL, NULL, NULL, NULL,
476                         learn_status_cb, &parm);
477   if (rc)
478     return unlock_scd (ctrl, map_assuan_err (rc));
479
480   return unlock_scd (ctrl, 0);
481 }
482
483
484 \f
485 static AssuanError
486 get_serialno_cb (void *opaque, const char *line)
487 {
488   char **serialno = opaque;
489   const char *keyword = line;
490   const char *s;
491   int keywordlen, n;
492
493   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
494     ;
495   while (spacep (line))
496     line++;
497
498   if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
499     {
500       if (*serialno)
501         return ASSUAN_Unexpected_Status;
502       for (n=0,s=line; hexdigitp (s); s++, n++)
503         ;
504       if (!n || (n&1)|| !(spacep (s) || !*s) )
505         return ASSUAN_Invalid_Status;
506       *serialno = xtrymalloc (n+1);
507       if (!*serialno)
508         return ASSUAN_Out_Of_Core;
509       memcpy (*serialno, line, n);
510       (*serialno)[n] = 0;
511     }
512   
513   return 0;
514 }
515
516 /* Return the serial number of the card or an appropriate error.  The
517    serial number is returned as a hexstring. */
518 int
519 agent_card_serialno (ctrl_t ctrl, char **r_serialno)
520 {
521   int rc;
522   char *serialno = NULL;
523
524   rc = start_scd (ctrl);
525   if (rc)
526     return rc;
527
528   rc = assuan_transact (ctrl->scd_local->ctx, "SERIALNO",
529                         NULL, NULL, NULL, NULL,
530                         get_serialno_cb, &serialno);
531   if (rc)
532     {
533       xfree (serialno);
534       return unlock_scd (ctrl, map_assuan_err (rc));
535     }
536   *r_serialno = serialno;
537   return unlock_scd (ctrl, 0);
538 }
539
540
541
542 \f
543 static AssuanError
544 membuf_data_cb (void *opaque, const void *buffer, size_t length)
545 {
546   membuf_t *data = opaque;
547
548   if (buffer)
549     put_membuf (data, buffer, length);
550   return 0;
551 }
552   
553 /* Handle the NEEDPIN inquiry. */
554 static AssuanError
555 inq_needpin (void *opaque, const char *line)
556 {
557   struct inq_needpin_s *parm = opaque;
558   char *pin;
559   size_t pinlen;
560   int rc;
561
562   if (!(!strncmp (line, "NEEDPIN", 7) && (line[7] == ' ' || !line[7])))
563     {
564       log_error ("unsupported inquiry `%s'\n", line);
565       return ASSUAN_Inquire_Unknown;
566     }
567   line += 7;
568
569   pinlen = 90;
570   pin = gcry_malloc_secure (pinlen);
571   if (!pin)
572     return ASSUAN_Out_Of_Core;
573
574   rc = parm->getpin_cb (parm->getpin_cb_arg, line, pin, pinlen);
575   if (rc)
576     rc = ASSUAN_Canceled;
577   if (!rc)
578     rc = assuan_send_data (parm->ctx, pin, pinlen);
579   xfree (pin);
580
581   return rc;
582 }
583
584
585
586 /* Create a signature using the current card */
587 int
588 agent_card_pksign (ctrl_t ctrl,
589                    const char *keyid,
590                    int (*getpin_cb)(void *, const char *, char*, size_t),
591                    void *getpin_cb_arg,
592                    const unsigned char *indata, size_t indatalen,
593                    char **r_buf, size_t *r_buflen)
594 {
595   int rc, i;
596   char *p, line[ASSUAN_LINELENGTH];
597   membuf_t data;
598   struct inq_needpin_s inqparm;
599   size_t len;
600   unsigned char *sigbuf;
601   size_t sigbuflen;
602
603   *r_buf = NULL;
604   rc = start_scd (ctrl);
605   if (rc)
606     return rc;
607
608   if (indatalen*2 + 50 > DIM(line))
609     return unlock_scd (ctrl, gpg_error (GPG_ERR_GENERAL));
610
611   sprintf (line, "SETDATA ");
612   p = line + strlen (line);
613   for (i=0; i < indatalen ; i++, p += 2 )
614     sprintf (p, "%02X", indata[i]);
615   rc = assuan_transact (ctrl->scd_local->ctx, line,
616                         NULL, NULL, NULL, NULL, NULL, NULL);
617   if (rc)
618     return unlock_scd (ctrl, map_assuan_err (rc));
619
620   init_membuf (&data, 1024);
621   inqparm.ctx = ctrl->scd_local->ctx;
622   inqparm.getpin_cb = getpin_cb;
623   inqparm.getpin_cb_arg = getpin_cb_arg;
624   snprintf (line, DIM(line)-1, 
625             ctrl->use_auth_call? "PKAUTH %s":"PKSIGN %s", keyid);
626   line[DIM(line)-1] = 0;
627   rc = assuan_transact (ctrl->scd_local->ctx, line,
628                         membuf_data_cb, &data,
629                         inq_needpin, &inqparm,
630                         NULL, NULL);
631   if (rc)
632     {
633       xfree (get_membuf (&data, &len));
634       return unlock_scd (ctrl, map_assuan_err (rc));
635     }
636   sigbuf = get_membuf (&data, &sigbuflen);
637
638   /* Create an S-expression from it which is formatted like this:
639      "(7:sig-val(3:rsa(1:sSIGBUFLEN:SIGBUF)))" */
640   *r_buflen = 21 + 11 + sigbuflen + 4;
641   *r_buf = xtrymalloc (*r_buflen);
642   if (!*r_buf)
643     {
644       gpg_error_t tmperr = out_of_core ();
645       xfree (*r_buf);
646       return unlock_scd (ctrl, tmperr);
647     }
648   p = stpcpy (*r_buf, "(7:sig-val(3:rsa(1:s" );
649   sprintf (p, "%u:", (unsigned int)sigbuflen);
650   p += strlen (p);
651   memcpy (p, sigbuf, sigbuflen);
652   p += sigbuflen;
653   strcpy (p, ")))");
654   xfree (sigbuf);
655
656   assert (gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL));
657   return unlock_scd (ctrl, 0);
658 }
659
660 /* Decipher INDATA using the current card. Note that the returned value is */
661 int
662 agent_card_pkdecrypt (ctrl_t ctrl,
663                       const char *keyid,
664                       int (*getpin_cb)(void *, const char *, char*, size_t),
665                       void *getpin_cb_arg,
666                       const unsigned char *indata, size_t indatalen,
667                       char **r_buf, size_t *r_buflen)
668 {
669   int rc, i;
670   char *p, line[ASSUAN_LINELENGTH];
671   membuf_t data;
672   struct inq_needpin_s inqparm;
673   size_t len;
674
675   *r_buf = NULL;
676   rc = start_scd (ctrl);
677   if (rc)
678     return rc;
679
680   /* FIXME: use secure memory where appropriate */
681   if (indatalen*2 + 50 > DIM(line))
682     return unlock_scd (ctrl, gpg_error (GPG_ERR_GENERAL));
683
684   sprintf (line, "SETDATA ");
685   p = line + strlen (line);
686   for (i=0; i < indatalen ; i++, p += 2 )
687     sprintf (p, "%02X", indata[i]);
688   rc = assuan_transact (ctrl->scd_local->ctx, line,
689                         NULL, NULL, NULL, NULL, NULL, NULL);
690   if (rc)
691     return unlock_scd (ctrl, map_assuan_err (rc));
692
693   init_membuf (&data, 1024);
694   inqparm.ctx = ctrl->scd_local->ctx;
695   inqparm.getpin_cb = getpin_cb;
696   inqparm.getpin_cb_arg = getpin_cb_arg;
697   snprintf (line, DIM(line)-1, "PKDECRYPT %s", keyid);
698   line[DIM(line)-1] = 0;
699   rc = assuan_transact (ctrl->scd_local->ctx, line,
700                         membuf_data_cb, &data,
701                         inq_needpin, &inqparm,
702                         NULL, NULL);
703   if (rc)
704     {
705       xfree (get_membuf (&data, &len));
706       return unlock_scd (ctrl, map_assuan_err (rc));
707     }
708   *r_buf = get_membuf (&data, r_buflen);
709   if (!*r_buf)
710     return unlock_scd (ctrl, gpg_error (GPG_ERR_ENOMEM));
711
712   return unlock_scd (ctrl, 0);
713 }
714
715
716 \f
717 /* Read a certificate with ID into R_BUF and R_BUFLEN. */
718 int
719 agent_card_readcert (ctrl_t ctrl,
720                      const char *id, char **r_buf, size_t *r_buflen)
721 {
722   int rc;
723   char line[ASSUAN_LINELENGTH];
724   membuf_t data;
725   size_t len;
726
727   *r_buf = NULL;
728   rc = start_scd (ctrl);
729   if (rc)
730     return rc;
731
732   init_membuf (&data, 1024);
733   snprintf (line, DIM(line)-1, "READCERT %s", id);
734   line[DIM(line)-1] = 0;
735   rc = assuan_transact (ctrl->scd_local->ctx, line,
736                         membuf_data_cb, &data,
737                         NULL, NULL,
738                         NULL, NULL);
739   if (rc)
740     {
741       xfree (get_membuf (&data, &len));
742       return unlock_scd (ctrl, map_assuan_err (rc));
743     }
744   *r_buf = get_membuf (&data, r_buflen);
745   if (!*r_buf)
746     return unlock_scd (ctrl, gpg_error (GPG_ERR_ENOMEM));
747
748   return unlock_scd (ctrl, 0);
749 }
750
751
752 \f
753 /* Read a key with ID and return it in an allocate buffer pointed to
754    by r_BUF as a valid S-expression. */
755 int
756 agent_card_readkey (ctrl_t ctrl, const char *id, unsigned char **r_buf)
757 {
758   int rc;
759   char line[ASSUAN_LINELENGTH];
760   membuf_t data;
761   size_t len, buflen;
762
763   *r_buf = NULL;
764   rc = start_scd (ctrl);
765   if (rc)
766     return rc;
767
768   init_membuf (&data, 1024);
769   snprintf (line, DIM(line)-1, "READKEY %s", id);
770   line[DIM(line)-1] = 0;
771   rc = assuan_transact (ctrl->scd_local->ctx, line,
772                         membuf_data_cb, &data,
773                         NULL, NULL,
774                         NULL, NULL);
775   if (rc)
776     {
777       xfree (get_membuf (&data, &len));
778       return unlock_scd (ctrl, map_assuan_err (rc));
779     }
780   *r_buf = get_membuf (&data, &buflen);
781   if (!*r_buf)
782     return unlock_scd (ctrl, gpg_error (GPG_ERR_ENOMEM));
783
784   if (!gcry_sexp_canon_len (*r_buf, buflen, NULL, NULL))
785     {
786       xfree (*r_buf); *r_buf = NULL;
787       return unlock_scd (ctrl, gpg_error (GPG_ERR_INV_VALUE));
788     }
789
790   return unlock_scd (ctrl, 0);
791 }
792
793
794 \f
795 /* Type used with the card_getattr_cb.  */
796 struct card_getattr_parm_s {
797   const char *keyword;  /* Keyword to look for.  */
798   size_t keywordlen;    /* strlen of KEYWORD.  */
799   char *data;           /* Malloced and unescaped data.  */
800   int error;            /* ERRNO value or 0 on success. */
801 };
802
803 /* Callback function for agent_card_getattr.  */
804 static assuan_error_t
805 card_getattr_cb (void *opaque, const char *line)
806 {
807   struct card_getattr_parm_s *parm = opaque;
808   const char *keyword = line;
809   int keywordlen;
810
811   if (parm->data)
812     return 0; /* We want only the first occurrence.  */
813
814   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
815     ;
816   while (spacep (line))
817     line++;
818
819   if (keywordlen == parm->keywordlen
820       && !memcmp (keyword, parm->keyword, keywordlen))
821     {
822       parm->data = unescape_status_string (line);
823       if (!parm->data)
824         parm->error = errno;
825     }
826   
827   return 0;
828 }
829
830
831 /* Call the agent to retrieve a single line data object. On success
832    the object is malloced and stored at RESULT; it is guaranteed that
833    NULL is never stored in this case.  On error an error code is
834    returned and NULL stored at RESULT. */
835 gpg_error_t
836 agent_card_getattr (ctrl_t ctrl, const char *name, char **result)
837 {
838   int err;
839   struct card_getattr_parm_s parm;
840   char line[ASSUAN_LINELENGTH];
841
842   *result = NULL;
843
844   if (!*name)
845     return gpg_error (GPG_ERR_INV_VALUE);
846
847   memset (&parm, 0, sizeof parm);
848   parm.keyword = name;
849   parm.keywordlen = strlen (name);
850
851   /* We assume that NAME does not need escaping. */
852   if (8 + strlen (name) > DIM(line)-1)
853     return gpg_error (GPG_ERR_TOO_LARGE);
854   stpcpy (stpcpy (line, "GETATTR "), name); 
855
856   err = start_scd (ctrl);
857   if (err)
858     return err;
859
860   err = map_assuan_err (assuan_transact (ctrl->scd_local->ctx, line,
861                                          NULL, NULL, NULL, NULL,
862                                          card_getattr_cb, &parm));
863   if (!err && parm.error)
864     err = gpg_error_from_errno (parm.error);
865   
866   if (!err && !parm.data)
867     err = gpg_error (GPG_ERR_NO_DATA);
868   
869   if (!err)
870     *result = parm.data;
871   else
872     xfree (parm.data);
873
874   return unlock_scd (ctrl, err);
875 }
876
877
878
879 \f
880 static AssuanError
881 pass_status_thru (void *opaque, const char *line)
882 {
883   ASSUAN_CONTEXT ctx = opaque;
884   char keyword[200];
885   int i;
886
887   for (i=0; *line && !spacep (line) && i < DIM(keyword)-1; line++, i++)
888     keyword[i] = *line;
889   keyword[i] = 0;
890   /* truncate any remaining keyword stuff. */
891   for (; *line && !spacep (line); line++)
892     ;
893   while (spacep (line))
894     line++;
895
896   assuan_write_status (ctx, keyword, line);
897   return 0;
898 }
899
900 static AssuanError
901 pass_data_thru (void *opaque, const void *buffer, size_t length)
902 {
903   ASSUAN_CONTEXT ctx = opaque;
904
905   assuan_send_data (ctx, buffer, length);
906   return 0;
907 }
908
909
910 /* Send the line CMDLINE with command for the SCDdaemon to it and send
911    all status messages back.  This command is used as a general quoting
912    mechanism to pass everything verbatim to SCDAEMOPN.  The PIN
913    inquirey is handled inside gpg-agent. */
914 int
915 agent_card_scd (ctrl_t ctrl, const char *cmdline,
916                 int (*getpin_cb)(void *, const char *, char*, size_t),
917                 void *getpin_cb_arg, void *assuan_context)
918 {
919   int rc;
920   struct inq_needpin_s inqparm;
921
922   rc = start_scd (ctrl);
923   if (rc)
924     return rc;
925
926   inqparm.ctx = ctrl->scd_local->ctx;
927   inqparm.getpin_cb = getpin_cb;
928   inqparm.getpin_cb_arg = getpin_cb_arg;
929   rc = assuan_transact (ctrl->scd_local->ctx, cmdline,
930                         pass_data_thru, assuan_context,
931                         inq_needpin, &inqparm,
932                         pass_status_thru, assuan_context);
933   if (rc)
934     {
935       return unlock_scd (ctrl, map_assuan_err (rc));
936     }
937
938   return unlock_scd (ctrl, 0);
939 }
940
941