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