* command.c (cmd_updatestartuptty): New.
[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   pid_t pid;
376   int rc;
377
378   /* We can do so only if there is no more active primary connection.
379      With an active primary connection, this is all no problem because
380      with the end of gpg-agent's session a disconnect is send and the
381      this function will be used at a later time. */
382   if (!primary_scd_ctx || !primary_scd_ctx_reusable)
383     return;
384
385   if (!pth_mutex_acquire (&start_scd_lock, 0, NULL))
386     {
387       log_error ("failed to acquire the start_scd lock while"
388                  " doing an aliveness check: %s\n",
389                  strerror (errno));
390       return;
391     }
392
393   if (primary_scd_ctx && primary_scd_ctx_reusable)
394     {
395       pid = assuan_get_pid (primary_scd_ctx);
396       if (pid != (pid_t)(-1) && pid
397           && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
398         {
399           /* Okay, scdaemon died.  Disconnect the primary connection now
400              but take care that it won't do another wait. */
401           assuan_set_flag (primary_scd_ctx, ASSUAN_NO_WAITPID, 1);
402           assuan_disconnect (primary_scd_ctx);
403           primary_scd_ctx = NULL;
404           primary_scd_ctx_reusable = 0;
405           xfree (socket_name);
406           socket_name = NULL;
407         }
408     }
409
410   if (!pth_mutex_release (&start_scd_lock))
411     log_error ("failed to release the start_scd lock while"
412                " doing the aliveness check: %s\n", strerror (errno));
413 }
414
415
416
417 /* Reset the SCD if it has been used. */
418 int
419 agent_reset_scd (ctrl_t ctrl)
420 {
421   if (ctrl->scd_local)
422     {
423       if (ctrl->scd_local->ctx)
424         {
425           /* We can't disconnect the primary context because libassuan
426              does a waitpid on it and thus the system would hang.
427              Instead we send a reset and keep that connection for
428              reuse. */
429           if (ctrl->scd_local->ctx == primary_scd_ctx)
430             {
431               /* The RESET may fail for example if the scdaemon has
432                  already been terminated.  We need to set the reusable
433                  flag anyway to make sure that the aliveness check can
434                  clean it up. */
435               assuan_transact (primary_scd_ctx, "RESET",
436                                NULL, NULL, NULL, NULL, NULL, NULL);
437               primary_scd_ctx_reusable = 1;
438             }
439           else
440             assuan_disconnect (ctrl->scd_local->ctx);
441         }
442       xfree (ctrl->scd_local);
443       ctrl->scd_local = NULL;
444     }
445
446   return 0;
447 }
448
449
450 \f
451 /* Return a new malloced string by unescaping the string S.  Escaping
452    is percent escaping and '+'/space mapping.  A binary Nul will
453    silently be replaced by a 0xFF.  Function returns NULL to indicate
454    an out of memory status. */
455 static char *
456 unescape_status_string (const unsigned char *s)
457 {
458   char *buffer, *d;
459
460   buffer = d = xtrymalloc (strlen (s)+1);
461   if (!buffer)
462     return NULL;
463   while (*s)
464     {
465       if (*s == '%' && s[1] && s[2])
466         { 
467           s++;
468           *d = xtoi_2 (s);
469           if (!*d)
470             *d = '\xff';
471           d++;
472           s += 2;
473         }
474       else if (*s == '+')
475         {
476           *d++ = ' ';
477           s++;
478         }
479       else
480         *d++ = *s++;
481     }
482   *d = 0; 
483   return buffer;
484 }
485
486
487 \f
488 static AssuanError
489 learn_status_cb (void *opaque, const char *line)
490 {
491   struct learn_parm_s *parm = opaque;
492   const char *keyword = line;
493   int keywordlen;
494
495   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
496     ;
497   while (spacep (line))
498     line++;
499   if (keywordlen == 8 && !memcmp (keyword, "CERTINFO", keywordlen))
500     {
501       parm->certinfo_cb (parm->certinfo_cb_arg, line);
502     }
503   else if (keywordlen == 11 && !memcmp (keyword, "KEYPAIRINFO", keywordlen))
504     {
505       parm->kpinfo_cb (parm->kpinfo_cb_arg, line);
506     }
507   else if (keywordlen && *line)
508     {
509       parm->sinfo_cb (parm->sinfo_cb_arg, keyword, keywordlen, line);
510     }
511   
512   return 0;
513 }
514
515 /* Perform the LEARN command and return a list of all private keys
516    stored on the card. */
517 int
518 agent_card_learn (ctrl_t ctrl,
519                   void (*kpinfo_cb)(void*, const char *),
520                   void *kpinfo_cb_arg,
521                   void (*certinfo_cb)(void*, const char *),
522                   void *certinfo_cb_arg,
523                   void (*sinfo_cb)(void*, const char *, size_t, const char *),
524                   void *sinfo_cb_arg)
525 {
526   int rc;
527   struct learn_parm_s parm;
528
529   rc = start_scd (ctrl);
530   if (rc)
531     return rc;
532
533   memset (&parm, 0, sizeof parm);
534   parm.kpinfo_cb = kpinfo_cb;
535   parm.kpinfo_cb_arg = kpinfo_cb_arg;
536   parm.certinfo_cb = certinfo_cb;
537   parm.certinfo_cb_arg = certinfo_cb_arg;
538   parm.sinfo_cb = sinfo_cb;
539   parm.sinfo_cb_arg = sinfo_cb_arg;
540   rc = assuan_transact (ctrl->scd_local->ctx, "LEARN --force",
541                         NULL, NULL, NULL, NULL,
542                         learn_status_cb, &parm);
543   if (rc)
544     return unlock_scd (ctrl, map_assuan_err (rc));
545
546   return unlock_scd (ctrl, 0);
547 }
548
549
550 \f
551 static AssuanError
552 get_serialno_cb (void *opaque, const char *line)
553 {
554   char **serialno = opaque;
555   const char *keyword = line;
556   const char *s;
557   int keywordlen, n;
558
559   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
560     ;
561   while (spacep (line))
562     line++;
563
564   if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
565     {
566       if (*serialno)
567         return ASSUAN_Unexpected_Status;
568       for (n=0,s=line; hexdigitp (s); s++, n++)
569         ;
570       if (!n || (n&1)|| !(spacep (s) || !*s) )
571         return ASSUAN_Invalid_Status;
572       *serialno = xtrymalloc (n+1);
573       if (!*serialno)
574         return ASSUAN_Out_Of_Core;
575       memcpy (*serialno, line, n);
576       (*serialno)[n] = 0;
577     }
578   
579   return 0;
580 }
581
582 /* Return the serial number of the card or an appropriate error.  The
583    serial number is returned as a hexstring. */
584 int
585 agent_card_serialno (ctrl_t ctrl, char **r_serialno)
586 {
587   int rc;
588   char *serialno = NULL;
589
590   rc = start_scd (ctrl);
591   if (rc)
592     return rc;
593
594   rc = assuan_transact (ctrl->scd_local->ctx, "SERIALNO",
595                         NULL, NULL, NULL, NULL,
596                         get_serialno_cb, &serialno);
597   if (rc)
598     {
599       xfree (serialno);
600       return unlock_scd (ctrl, map_assuan_err (rc));
601     }
602   *r_serialno = serialno;
603   return unlock_scd (ctrl, 0);
604 }
605
606
607
608 \f
609 static AssuanError
610 membuf_data_cb (void *opaque, const void *buffer, size_t length)
611 {
612   membuf_t *data = opaque;
613
614   if (buffer)
615     put_membuf (data, buffer, length);
616   return 0;
617 }
618   
619 /* Handle the NEEDPIN inquiry. */
620 static AssuanError
621 inq_needpin (void *opaque, const char *line)
622 {
623   struct inq_needpin_s *parm = opaque;
624   char *pin;
625   size_t pinlen;
626   int rc;
627
628   if (!(!strncmp (line, "NEEDPIN", 7) && (line[7] == ' ' || !line[7])))
629     {
630       log_error ("unsupported inquiry `%s'\n", line);
631       return ASSUAN_Inquire_Unknown;
632     }
633   line += 7;
634   while (*line == ' ')
635     line++;
636
637   pinlen = 90;
638   pin = gcry_malloc_secure (pinlen);
639   if (!pin)
640     return ASSUAN_Out_Of_Core;
641
642   rc = parm->getpin_cb (parm->getpin_cb_arg, line, pin, pinlen);
643   if (rc)
644     rc = ASSUAN_Canceled;
645   if (!rc)
646     rc = assuan_send_data (parm->ctx, pin, pinlen);
647   xfree (pin);
648
649   return rc;
650 }
651
652
653
654 /* Create a signature using the current card */
655 int
656 agent_card_pksign (ctrl_t ctrl,
657                    const char *keyid,
658                    int (*getpin_cb)(void *, const char *, char*, size_t),
659                    void *getpin_cb_arg,
660                    const unsigned char *indata, size_t indatalen,
661                    char **r_buf, size_t *r_buflen)
662 {
663   int rc, i;
664   char *p, line[ASSUAN_LINELENGTH];
665   membuf_t data;
666   struct inq_needpin_s inqparm;
667   size_t len;
668   unsigned char *sigbuf;
669   size_t sigbuflen;
670
671   *r_buf = NULL;
672   rc = start_scd (ctrl);
673   if (rc)
674     return rc;
675
676   if (indatalen*2 + 50 > DIM(line))
677     return unlock_scd (ctrl, gpg_error (GPG_ERR_GENERAL));
678
679   sprintf (line, "SETDATA ");
680   p = line + strlen (line);
681   for (i=0; i < indatalen ; i++, p += 2 )
682     sprintf (p, "%02X", indata[i]);
683   rc = assuan_transact (ctrl->scd_local->ctx, line,
684                         NULL, NULL, NULL, NULL, NULL, NULL);
685   if (rc)
686     return unlock_scd (ctrl, map_assuan_err (rc));
687
688   init_membuf (&data, 1024);
689   inqparm.ctx = ctrl->scd_local->ctx;
690   inqparm.getpin_cb = getpin_cb;
691   inqparm.getpin_cb_arg = getpin_cb_arg;
692   snprintf (line, DIM(line)-1, 
693             ctrl->use_auth_call? "PKAUTH %s":"PKSIGN %s", keyid);
694   line[DIM(line)-1] = 0;
695   rc = assuan_transact (ctrl->scd_local->ctx, line,
696                         membuf_data_cb, &data,
697                         inq_needpin, &inqparm,
698                         NULL, NULL);
699   if (rc)
700     {
701       xfree (get_membuf (&data, &len));
702       return unlock_scd (ctrl, map_assuan_err (rc));
703     }
704   sigbuf = get_membuf (&data, &sigbuflen);
705
706   /* Create an S-expression from it which is formatted like this:
707      "(7:sig-val(3:rsa(1:sSIGBUFLEN:SIGBUF)))" */
708   *r_buflen = 21 + 11 + sigbuflen + 4;
709   *r_buf = xtrymalloc (*r_buflen);
710   if (!*r_buf)
711     {
712       gpg_error_t tmperr = out_of_core ();
713       xfree (*r_buf);
714       return unlock_scd (ctrl, tmperr);
715     }
716   p = stpcpy (*r_buf, "(7:sig-val(3:rsa(1:s" );
717   sprintf (p, "%u:", (unsigned int)sigbuflen);
718   p += strlen (p);
719   memcpy (p, sigbuf, sigbuflen);
720   p += sigbuflen;
721   strcpy (p, ")))");
722   xfree (sigbuf);
723
724   assert (gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL));
725   return unlock_scd (ctrl, 0);
726 }
727
728 /* Decipher INDATA using the current card. Note that the returned value is */
729 int
730 agent_card_pkdecrypt (ctrl_t ctrl,
731                       const char *keyid,
732                       int (*getpin_cb)(void *, const char *, char*, size_t),
733                       void *getpin_cb_arg,
734                       const unsigned char *indata, size_t indatalen,
735                       char **r_buf, size_t *r_buflen)
736 {
737   int rc, i;
738   char *p, line[ASSUAN_LINELENGTH];
739   membuf_t data;
740   struct inq_needpin_s inqparm;
741   size_t len;
742
743   *r_buf = NULL;
744   rc = start_scd (ctrl);
745   if (rc)
746     return rc;
747
748   /* FIXME: use secure memory where appropriate */
749   if (indatalen*2 + 50 > DIM(line))
750     return unlock_scd (ctrl, gpg_error (GPG_ERR_GENERAL));
751
752   sprintf (line, "SETDATA ");
753   p = line + strlen (line);
754   for (i=0; i < indatalen ; i++, p += 2 )
755     sprintf (p, "%02X", indata[i]);
756   rc = assuan_transact (ctrl->scd_local->ctx, line,
757                         NULL, NULL, NULL, NULL, NULL, NULL);
758   if (rc)
759     return unlock_scd (ctrl, map_assuan_err (rc));
760
761   init_membuf (&data, 1024);
762   inqparm.ctx = ctrl->scd_local->ctx;
763   inqparm.getpin_cb = getpin_cb;
764   inqparm.getpin_cb_arg = getpin_cb_arg;
765   snprintf (line, DIM(line)-1, "PKDECRYPT %s", keyid);
766   line[DIM(line)-1] = 0;
767   rc = assuan_transact (ctrl->scd_local->ctx, line,
768                         membuf_data_cb, &data,
769                         inq_needpin, &inqparm,
770                         NULL, NULL);
771   if (rc)
772     {
773       xfree (get_membuf (&data, &len));
774       return unlock_scd (ctrl, map_assuan_err (rc));
775     }
776   *r_buf = get_membuf (&data, r_buflen);
777   if (!*r_buf)
778     return unlock_scd (ctrl, gpg_error (GPG_ERR_ENOMEM));
779
780   return unlock_scd (ctrl, 0);
781 }
782
783
784 \f
785 /* Read a certificate with ID into R_BUF and R_BUFLEN. */
786 int
787 agent_card_readcert (ctrl_t ctrl,
788                      const char *id, char **r_buf, size_t *r_buflen)
789 {
790   int rc;
791   char line[ASSUAN_LINELENGTH];
792   membuf_t data;
793   size_t len;
794
795   *r_buf = NULL;
796   rc = start_scd (ctrl);
797   if (rc)
798     return rc;
799
800   init_membuf (&data, 1024);
801   snprintf (line, DIM(line)-1, "READCERT %s", id);
802   line[DIM(line)-1] = 0;
803   rc = assuan_transact (ctrl->scd_local->ctx, line,
804                         membuf_data_cb, &data,
805                         NULL, NULL,
806                         NULL, NULL);
807   if (rc)
808     {
809       xfree (get_membuf (&data, &len));
810       return unlock_scd (ctrl, map_assuan_err (rc));
811     }
812   *r_buf = get_membuf (&data, r_buflen);
813   if (!*r_buf)
814     return unlock_scd (ctrl, gpg_error (GPG_ERR_ENOMEM));
815
816   return unlock_scd (ctrl, 0);
817 }
818
819
820 \f
821 /* Read a key with ID and return it in an allocate buffer pointed to
822    by r_BUF as a valid S-expression. */
823 int
824 agent_card_readkey (ctrl_t ctrl, const char *id, unsigned char **r_buf)
825 {
826   int rc;
827   char line[ASSUAN_LINELENGTH];
828   membuf_t data;
829   size_t len, buflen;
830
831   *r_buf = NULL;
832   rc = start_scd (ctrl);
833   if (rc)
834     return rc;
835
836   init_membuf (&data, 1024);
837   snprintf (line, DIM(line)-1, "READKEY %s", id);
838   line[DIM(line)-1] = 0;
839   rc = assuan_transact (ctrl->scd_local->ctx, line,
840                         membuf_data_cb, &data,
841                         NULL, NULL,
842                         NULL, NULL);
843   if (rc)
844     {
845       xfree (get_membuf (&data, &len));
846       return unlock_scd (ctrl, map_assuan_err (rc));
847     }
848   *r_buf = get_membuf (&data, &buflen);
849   if (!*r_buf)
850     return unlock_scd (ctrl, gpg_error (GPG_ERR_ENOMEM));
851
852   if (!gcry_sexp_canon_len (*r_buf, buflen, NULL, NULL))
853     {
854       xfree (*r_buf); *r_buf = NULL;
855       return unlock_scd (ctrl, gpg_error (GPG_ERR_INV_VALUE));
856     }
857
858   return unlock_scd (ctrl, 0);
859 }
860
861
862 \f
863 /* Type used with the card_getattr_cb.  */
864 struct card_getattr_parm_s {
865   const char *keyword;  /* Keyword to look for.  */
866   size_t keywordlen;    /* strlen of KEYWORD.  */
867   char *data;           /* Malloced and unescaped data.  */
868   int error;            /* ERRNO value or 0 on success. */
869 };
870
871 /* Callback function for agent_card_getattr.  */
872 static assuan_error_t
873 card_getattr_cb (void *opaque, const char *line)
874 {
875   struct card_getattr_parm_s *parm = opaque;
876   const char *keyword = line;
877   int keywordlen;
878
879   if (parm->data)
880     return 0; /* We want only the first occurrence.  */
881
882   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
883     ;
884   while (spacep (line))
885     line++;
886
887   if (keywordlen == parm->keywordlen
888       && !memcmp (keyword, parm->keyword, keywordlen))
889     {
890       parm->data = unescape_status_string (line);
891       if (!parm->data)
892         parm->error = errno;
893     }
894   
895   return 0;
896 }
897
898
899 /* Call the agent to retrieve a single line data object. On success
900    the object is malloced and stored at RESULT; it is guaranteed that
901    NULL is never stored in this case.  On error an error code is
902    returned and NULL stored at RESULT. */
903 gpg_error_t
904 agent_card_getattr (ctrl_t ctrl, const char *name, char **result)
905 {
906   int err;
907   struct card_getattr_parm_s parm;
908   char line[ASSUAN_LINELENGTH];
909
910   *result = NULL;
911
912   if (!*name)
913     return gpg_error (GPG_ERR_INV_VALUE);
914
915   memset (&parm, 0, sizeof parm);
916   parm.keyword = name;
917   parm.keywordlen = strlen (name);
918
919   /* We assume that NAME does not need escaping. */
920   if (8 + strlen (name) > DIM(line)-1)
921     return gpg_error (GPG_ERR_TOO_LARGE);
922   stpcpy (stpcpy (line, "GETATTR "), name); 
923
924   err = start_scd (ctrl);
925   if (err)
926     return err;
927
928   err = map_assuan_err (assuan_transact (ctrl->scd_local->ctx, line,
929                                          NULL, NULL, NULL, NULL,
930                                          card_getattr_cb, &parm));
931   if (!err && parm.error)
932     err = gpg_error_from_errno (parm.error);
933   
934   if (!err && !parm.data)
935     err = gpg_error (GPG_ERR_NO_DATA);
936   
937   if (!err)
938     *result = parm.data;
939   else
940     xfree (parm.data);
941
942   return unlock_scd (ctrl, err);
943 }
944
945
946
947 \f
948 static AssuanError
949 pass_status_thru (void *opaque, const char *line)
950 {
951   ASSUAN_CONTEXT ctx = opaque;
952   char keyword[200];
953   int i;
954
955   for (i=0; *line && !spacep (line) && i < DIM(keyword)-1; line++, i++)
956     keyword[i] = *line;
957   keyword[i] = 0;
958   /* truncate any remaining keyword stuff. */
959   for (; *line && !spacep (line); line++)
960     ;
961   while (spacep (line))
962     line++;
963
964   assuan_write_status (ctx, keyword, line);
965   return 0;
966 }
967
968 static AssuanError
969 pass_data_thru (void *opaque, const void *buffer, size_t length)
970 {
971   ASSUAN_CONTEXT ctx = opaque;
972
973   assuan_send_data (ctx, buffer, length);
974   return 0;
975 }
976
977
978 /* Send the line CMDLINE with command for the SCDdaemon to it and send
979    all status messages back.  This command is used as a general quoting
980    mechanism to pass everything verbatim to SCDAEMOPN.  The PIN
981    inquirey is handled inside gpg-agent. */
982 int
983 agent_card_scd (ctrl_t ctrl, const char *cmdline,
984                 int (*getpin_cb)(void *, const char *, char*, size_t),
985                 void *getpin_cb_arg, void *assuan_context)
986 {
987   int rc;
988   struct inq_needpin_s inqparm;
989
990   rc = start_scd (ctrl);
991   if (rc)
992     return rc;
993
994   inqparm.ctx = ctrl->scd_local->ctx;
995   inqparm.getpin_cb = getpin_cb;
996   inqparm.getpin_cb_arg = getpin_cb_arg;
997   rc = assuan_transact (ctrl->scd_local->ctx, cmdline,
998                         pass_data_thru, assuan_context,
999                         inq_needpin, &inqparm,
1000                         pass_status_thru, assuan_context);
1001   if (rc)
1002     {
1003       return unlock_scd (ctrl, map_assuan_err (rc));
1004     }
1005
1006   return unlock_scd (ctrl, 0);
1007 }
1008
1009