* call-scd.c (atfork_cb): New.
[gnupg.git] / agent / call-scd.c
1 /* call-scd.c - fork of the scdaemon to do SC operations
2  *      Copyright (C) 2001, 2002 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 /* Fixme: For now we have serialized all access to the scdaemon which
22    make sense becuase the scdaemon can't handle concurrent connections
23    right now.  We should however keep a list of connections and lock
24    just that connection - it migth make sense to implemtn parts of
25    this in Assuan.*/
26
27 #include <config.h>
28 #include <errno.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <ctype.h>
33 #include <assert.h>
34 #include <unistd.h>
35 #include <sys/stat.h>
36 #ifdef USE_GNU_PTH
37 # include <pth.h>
38 #endif
39
40 #include "agent.h"
41 #include <assuan.h>
42
43 #ifdef _POSIX_OPEN_MAX
44 #define MAX_OPEN_FDS _POSIX_OPEN_MAX
45 #else
46 #define MAX_OPEN_FDS 20
47 #endif
48
49 static ASSUAN_CONTEXT scd_ctx = NULL;
50 #ifdef USE_GNU_PTH
51 static pth_mutex_t scd_lock = PTH_MUTEX_INIT;
52 #endif
53
54 /* callback parameter for learn card */
55 struct learn_parm_s {
56   void (*kpinfo_cb)(void*, const char *);
57   void *kpinfo_cb_arg;
58   void (*certinfo_cb)(void*, const char *);
59   void *certinfo_cb_arg;
60   void (*sinfo_cb)(void*, const char *, size_t, const char *);
61   void *sinfo_cb_arg;
62 };
63
64 struct inq_needpin_s {
65   ASSUAN_CONTEXT ctx;
66   int (*getpin_cb)(void *, const char *, char*, size_t);
67   void *getpin_cb_arg;
68 };
69
70 struct membuf {
71   size_t len;
72   size_t size;
73   char *buf;
74   int out_of_core;
75 };
76
77
78 \f
79 /* A simple implementation of a dynamic buffer.  Use init_membuf() to
80    create a buffer, put_membuf to append bytes and get_membuf to
81    release and return the buffer.  Allocation errors are detected but
82    only returned at the final get_membuf(), this helps not to clutter
83    the code with out of core checks.  */
84
85 static void
86 init_membuf (struct membuf *mb, int initiallen)
87 {
88   mb->len = 0;
89   mb->size = initiallen;
90   mb->out_of_core = 0;
91   mb->buf = xtrymalloc (initiallen);
92   if (!mb->buf)
93       mb->out_of_core = 1;
94 }
95
96 static void
97 put_membuf (struct membuf *mb, const void *buf, size_t len)
98 {
99   if (mb->out_of_core)
100     return;
101
102   if (mb->len + len >= mb->size)
103     {
104       char *p;
105       
106       mb->size += len + 1024;
107       p = xtryrealloc (mb->buf, mb->size);
108       if (!p)
109         {
110           mb->out_of_core = 1;
111           return;
112         }
113       mb->buf = p;
114     }
115   memcpy (mb->buf + mb->len, buf, len);
116   mb->len += len;
117 }
118
119 static void *
120 get_membuf (struct membuf *mb, size_t *len)
121 {
122   char *p;
123
124   if (mb->out_of_core)
125     {
126       xfree (mb->buf);
127       mb->buf = NULL;
128       return NULL;
129     }
130
131   p = mb->buf;
132   *len = mb->len;
133   mb->buf = NULL;
134   mb->out_of_core = 1; /* don't allow a reuse */
135   return p;
136 }
137
138
139
140 \f
141 static int 
142 unlock_scd (int rc)
143 {
144 #ifdef USE_GNU_PTH
145   if (!pth_mutex_release (&scd_lock))
146     {
147       log_error ("failed to release the SCD lock\n");
148       if (!rc)
149         rc = gpg_error (GPG_ERR_INTERNAL);
150     }
151 #endif
152   return rc;
153 }
154
155 /* To make sure we leave no secrets in our image after forking of the
156    scdaemon, we use this callback. */
157 static void
158 atfork_cb (void *opaque, int where)
159 {
160   if (!where)
161     gcry_control (GCRYCTL_TERM_SECMEM);
162 }
163
164
165 /* Fork off the SCdaemon if this has not already been done */
166 static int
167 start_scd (void)
168 {
169   int rc;
170   const char *pgmname;
171   ASSUAN_CONTEXT ctx;
172   const char *argv[3];
173   int no_close_list[3];
174   int i;
175
176 #ifdef USE_GNU_PTH
177   if (!pth_mutex_acquire (&scd_lock, 0, NULL))
178     {
179       log_error ("failed to acquire the SCD lock\n");
180       return gpg_error (GPG_ERR_INTERNAL);
181     }
182 #endif
183
184   if (scd_ctx)
185     return 0; /* No need to serialize things because the agent is
186                  expected to tun as a single-thread (or may be in
187                  future using libpth) */
188
189   if (opt.verbose)
190     log_info ("no running SCdaemon - starting it\n");
191       
192   if (fflush (NULL))
193     {
194       gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
195       log_error ("error flushing pending output: %s\n", strerror (errno));
196       return unlock_scd (tmperr);
197     }
198
199   if (!opt.scdaemon_program || !*opt.scdaemon_program)
200     opt.scdaemon_program = GNUPG_DEFAULT_SCDAEMON;
201   if ( !(pgmname = strrchr (opt.scdaemon_program, '/')))
202     pgmname = opt.scdaemon_program;
203   else
204     pgmname++;
205
206   argv[0] = pgmname;
207   argv[1] = "--server";
208   argv[2] = NULL;
209
210   i=0;
211   if (!opt.running_detached)
212     {
213       if (log_get_fd () != -1)
214         no_close_list[i++] = log_get_fd ();
215       no_close_list[i++] = fileno (stderr);
216     }
217   no_close_list[i] = -1;
218
219   /* Connect to the pinentry and perform initial handshaking */
220   rc = assuan_pipe_connect2 (&ctx, opt.scdaemon_program, (char**)argv,
221                              no_close_list, atfork_cb, NULL);
222   if (rc)
223     {
224       log_error ("can't connect to the SCdaemon: %s\n",
225                  assuan_strerror (rc));
226       return unlock_scd (gpg_error (GPG_ERR_NO_SCDAEMON));
227     }
228   scd_ctx = ctx;
229   
230   if (DBG_ASSUAN)
231     log_debug ("connection to SCdaemon established\n");
232   return 0;
233 }
234
235
236 \f
237 static AssuanError
238 learn_status_cb (void *opaque, const char *line)
239 {
240   struct learn_parm_s *parm = opaque;
241   const char *keyword = line;
242   int keywordlen;
243
244   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
245     ;
246   while (spacep (line))
247     line++;
248   if (keywordlen == 8 && !memcmp (keyword, "CERTINFO", keywordlen))
249     {
250       parm->certinfo_cb (parm->certinfo_cb_arg, line);
251     }
252   else if (keywordlen == 11 && !memcmp (keyword, "KEYPAIRINFO", keywordlen))
253     {
254       parm->kpinfo_cb (parm->kpinfo_cb_arg, line);
255     }
256   else if (keywordlen && *line)
257     {
258       parm->sinfo_cb (parm->sinfo_cb_arg, keyword, keywordlen, line);
259     }
260   
261   return 0;
262 }
263
264 /* Perform the learn command and return a list of all private keys
265    stored on the card. */
266 int
267 agent_card_learn (void (*kpinfo_cb)(void*, const char *),
268                   void *kpinfo_cb_arg,
269                   void (*certinfo_cb)(void*, const char *),
270                   void *certinfo_cb_arg,
271                   void (*sinfo_cb)(void*, const char *, size_t, const char *),
272                   void *sinfo_cb_arg)
273 {
274   int rc;
275   struct learn_parm_s parm;
276
277   rc = start_scd ();
278   if (rc)
279     return rc;
280
281   memset (&parm, 0, sizeof parm);
282   parm.kpinfo_cb = kpinfo_cb;
283   parm.kpinfo_cb_arg = kpinfo_cb_arg;
284   parm.certinfo_cb = certinfo_cb;
285   parm.certinfo_cb_arg = certinfo_cb_arg;
286   parm.sinfo_cb = sinfo_cb;
287   parm.sinfo_cb_arg = sinfo_cb_arg;
288   rc = assuan_transact (scd_ctx, "LEARN --force",
289                         NULL, NULL, NULL, NULL,
290                         learn_status_cb, &parm);
291   if (rc)
292     return unlock_scd (map_assuan_err (rc));
293
294   return unlock_scd (0);
295 }
296
297
298 \f
299 static AssuanError
300 get_serialno_cb (void *opaque, const char *line)
301 {
302   char **serialno = opaque;
303   const char *keyword = line;
304   const char *s;
305   int keywordlen, n;
306
307   for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
308     ;
309   while (spacep (line))
310     line++;
311
312   if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
313     {
314       if (*serialno)
315         return ASSUAN_Unexpected_Status;
316       for (n=0,s=line; hexdigitp (s); s++, n++)
317         ;
318       if (!n || (n&1)|| !(spacep (s) || !*s) )
319         return ASSUAN_Invalid_Status;
320       *serialno = xtrymalloc (n+1);
321       if (!*serialno)
322         return ASSUAN_Out_Of_Core;
323       memcpy (*serialno, line, n);
324       (*serialno)[n] = 0;
325     }
326   
327   return 0;
328 }
329
330 /* Return the serial number of the card or an appropriate error.  The
331    serial number is returned as a hexstring. */
332 int
333 agent_card_serialno (char **r_serialno)
334 {
335   int rc;
336   char *serialno = NULL;
337
338   rc = start_scd ();
339   if (rc)
340     return rc;
341
342   /* Hmm, do we really need this reset - scddaemon should do this or
343      we can do this if we for some reason figure out that the
344      operation might have failed due to a missing RESET.  Hmmm, I feel
345      this is really SCdaemon's duty */
346 /*    rc = assuan_transact (scd_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL); */
347 /*    if (rc) */
348 /*      return unlock_scd (map_assuan_err (rc)); */
349
350   rc = assuan_transact (scd_ctx, "SERIALNO",
351                         NULL, NULL, NULL, NULL,
352                         get_serialno_cb, &serialno);
353   if (rc)
354     {
355       xfree (serialno);
356       return unlock_scd (map_assuan_err (rc));
357     }
358   *r_serialno = serialno;
359   return unlock_scd (0);
360 }
361
362 \f
363 static AssuanError
364 membuf_data_cb (void *opaque, const void *buffer, size_t length)
365 {
366   struct membuf *data = opaque;
367
368   if (buffer)
369     put_membuf (data, buffer, length);
370   return 0;
371 }
372   
373 /* Handle the NEEDPIN inquiry. */
374 static AssuanError
375 inq_needpin (void *opaque, const char *line)
376 {
377   struct inq_needpin_s *parm = opaque;
378   char *pin;
379   size_t pinlen;
380   int rc;
381
382   if (!(!strncmp (line, "NEEDPIN", 7) && (line[7] == ' ' || !line[7])))
383     {
384       log_error ("unsupported inquiry `%s'\n", line);
385       return ASSUAN_Inquire_Unknown;
386     }
387   line += 7;
388
389   pinlen = 90;
390   pin = gcry_malloc_secure (pinlen);
391   if (!pin)
392     return ASSUAN_Out_Of_Core;
393
394   rc = parm->getpin_cb (parm->getpin_cb_arg, line, pin, pinlen);
395   if (rc)
396     rc = ASSUAN_Canceled;
397   if (!rc)
398     rc = assuan_send_data (parm->ctx, pin, pinlen);
399   xfree (pin);
400
401   return rc;
402 }
403
404
405
406 /* Create a signature using the current card */
407 int
408 agent_card_pksign (const char *keyid,
409                    int (*getpin_cb)(void *, const char *, char*, size_t),
410                    void *getpin_cb_arg,
411                    const unsigned char *indata, size_t indatalen,
412                    char **r_buf, size_t *r_buflen)
413 {
414   int rc, i;
415   char *p, line[ASSUAN_LINELENGTH];
416   struct membuf data;
417   struct inq_needpin_s inqparm;
418   size_t len;
419   unsigned char *sigbuf;
420   size_t sigbuflen;
421
422   *r_buf = NULL;
423   rc = start_scd ();
424   if (rc)
425     return rc;
426
427   if (indatalen*2 + 50 > DIM(line))
428     return unlock_scd (gpg_error (GPG_ERR_GENERAL));
429
430   sprintf (line, "SETDATA ");
431   p = line + strlen (line);
432   for (i=0; i < indatalen ; i++, p += 2 )
433     sprintf (p, "%02X", indata[i]);
434   rc = assuan_transact (scd_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
435   if (rc)
436     return unlock_scd (map_assuan_err (rc));
437
438   init_membuf (&data, 1024);
439   inqparm.ctx = scd_ctx;
440   inqparm.getpin_cb = getpin_cb;
441   inqparm.getpin_cb_arg = getpin_cb_arg;
442   snprintf (line, DIM(line)-1, "PKSIGN %s", keyid);
443   line[DIM(line)-1] = 0;
444   rc = assuan_transact (scd_ctx, line,
445                         membuf_data_cb, &data,
446                         inq_needpin, &inqparm,
447                         NULL, NULL);
448   if (rc)
449     {
450       xfree (get_membuf (&data, &len));
451       return unlock_scd (map_assuan_err (rc));
452     }
453   sigbuf = get_membuf (&data, &sigbuflen);
454
455   /* create an S-expression from it which is formatted like this:
456      "(7:sig-val(3:rsa(1:sSIGBUFLEN:SIGBUF)))" */
457   *r_buflen = 21 + 11 + sigbuflen + 4;
458   *r_buf = xtrymalloc (*r_buflen);
459   if (!*r_buf)
460     {
461       gpg_error_t tmperr = out_of_core ();
462       xfree (*r_buf);
463       return unlock_scd (tmperr);
464     }
465   p = stpcpy (*r_buf, "(7:sig-val(3:rsa(1:s" );
466   sprintf (p, "%u:", (unsigned int)sigbuflen);
467   p += strlen (p);
468   memcpy (p, sigbuf, sigbuflen);
469   p += sigbuflen;
470   strcpy (p, ")))");
471   xfree (sigbuf);
472
473   assert (gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL));
474   return unlock_scd (0);
475 }
476
477 /* Decipher INDATA using the current card. Note that the returned value is */
478 int
479 agent_card_pkdecrypt (const char *keyid,
480                    int (*getpin_cb)(void *, const char *, char*, size_t),
481                    void *getpin_cb_arg,
482                    const unsigned char *indata, size_t indatalen,
483                    char **r_buf, size_t *r_buflen)
484 {
485   int rc, i;
486   char *p, line[ASSUAN_LINELENGTH];
487   struct membuf data;
488   struct inq_needpin_s inqparm;
489   size_t len;
490
491   *r_buf = NULL;
492   rc = start_scd ();
493   if (rc)
494     return rc;
495
496   /* FIXME: use secure memory where appropriate */
497   if (indatalen*2 + 50 > DIM(line))
498     return unlock_scd (gpg_error (GPG_ERR_GENERAL));
499
500   sprintf (line, "SETDATA ");
501   p = line + strlen (line);
502   for (i=0; i < indatalen ; i++, p += 2 )
503     sprintf (p, "%02X", indata[i]);
504   rc = assuan_transact (scd_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
505   if (rc)
506     return unlock_scd (map_assuan_err (rc));
507
508   init_membuf (&data, 1024);
509   inqparm.ctx = scd_ctx;
510   inqparm.getpin_cb = getpin_cb;
511   inqparm.getpin_cb_arg = getpin_cb_arg;
512   snprintf (line, DIM(line)-1, "PKDECRYPT %s", keyid);
513   line[DIM(line)-1] = 0;
514   rc = assuan_transact (scd_ctx, line,
515                         membuf_data_cb, &data,
516                         inq_needpin, &inqparm,
517                         NULL, NULL);
518   if (rc)
519     {
520       xfree (get_membuf (&data, &len));
521       return unlock_scd (map_assuan_err (rc));
522     }
523   *r_buf = get_membuf (&data, r_buflen);
524   if (!*r_buf)
525     return unlock_scd (gpg_error (GPG_ERR_ENOMEM));
526
527   return unlock_scd (0);
528 }
529
530
531 \f
532 /* Read a certificate with ID into R_BUF and R_BUFLEN. */
533 int
534 agent_card_readcert (const char *id, char **r_buf, size_t *r_buflen)
535 {
536   int rc;
537   char line[ASSUAN_LINELENGTH];
538   struct membuf data;
539   size_t len;
540
541   *r_buf = NULL;
542   rc = start_scd ();
543   if (rc)
544     return rc;
545
546   init_membuf (&data, 1024);
547   snprintf (line, DIM(line)-1, "READCERT %s", id);
548   line[DIM(line)-1] = 0;
549   rc = assuan_transact (scd_ctx, line,
550                         membuf_data_cb, &data,
551                         NULL, NULL,
552                         NULL, NULL);
553   if (rc)
554     {
555       xfree (get_membuf (&data, &len));
556       return unlock_scd (map_assuan_err (rc));
557     }
558   *r_buf = get_membuf (&data, r_buflen);
559   if (!*r_buf)
560     return unlock_scd (gpg_error (GPG_ERR_ENOMEM));
561
562   return unlock_scd (0);
563 }
564
565
566 \f
567 /* Read a key with ID and return it in an allocate buffer pointed to
568    by r_BUF as a valid S-expression. */
569 int
570 agent_card_readkey (const char *id, unsigned char **r_buf)
571 {
572   int rc;
573   char line[ASSUAN_LINELENGTH];
574   struct membuf data;
575   size_t len, buflen;
576
577   *r_buf = NULL;
578   rc = start_scd ();
579   if (rc)
580     return rc;
581
582   init_membuf (&data, 1024);
583   snprintf (line, DIM(line)-1, "READKEY %s", id);
584   line[DIM(line)-1] = 0;
585   rc = assuan_transact (scd_ctx, line,
586                         membuf_data_cb, &data,
587                         NULL, NULL,
588                         NULL, NULL);
589   if (rc)
590     {
591       xfree (get_membuf (&data, &len));
592       return unlock_scd (map_assuan_err (rc));
593     }
594   *r_buf = get_membuf (&data, &buflen);
595   if (!*r_buf)
596     return unlock_scd (gpg_error (GPG_ERR_ENOMEM));
597
598   if (!gcry_sexp_canon_len (*r_buf, buflen, NULL, NULL))
599     {
600       xfree (*r_buf); *r_buf = NULL;
601       return unlock_scd (gpg_error (GPG_ERR_INV_VALUE));
602     }
603
604   return unlock_scd (0);
605 }
606
607
608
609 \f
610 static AssuanError
611 pass_status_thru (void *opaque, const char *line)
612 {
613   ASSUAN_CONTEXT ctx = opaque;
614   char keyword[200];
615   int i;
616
617   for (i=0; *line && !spacep (line) && i < DIM(keyword)-1; line++, i++)
618     keyword[i] = *line;
619   keyword[i] = 0;
620   /* truncate any remaining keyword stuff. */
621   for (; *line && !spacep (line); line++)
622     ;
623   while (spacep (line))
624     line++;
625
626   assuan_write_status (ctx, keyword, line);
627   return 0;
628 }
629
630 static AssuanError
631 pass_data_thru (void *opaque, const void *buffer, size_t length)
632 {
633   ASSUAN_CONTEXT ctx = opaque;
634
635   assuan_send_data (ctx, buffer, length);
636   return 0;
637 }
638
639
640 /* Send the line CMDLINE with command for the SCDdaemon to it and send
641    all status messages back.  This command is used as a general quoting
642    mechanism to pass everything verbatim to SCDAEMOPN.  The PIN
643    inquirey is handled inside gpg-agent. */
644 int
645 agent_card_scd (const char *cmdline,
646                 int (*getpin_cb)(void *, const char *, char*, size_t),
647                 void *getpin_cb_arg, void *assuan_context)
648 {
649   int rc;
650   struct inq_needpin_s inqparm;
651
652   rc = start_scd ();
653   if (rc)
654     return rc;
655
656   inqparm.ctx = scd_ctx;
657   inqparm.getpin_cb = getpin_cb;
658   inqparm.getpin_cb_arg = getpin_cb_arg;
659   rc = assuan_transact (scd_ctx, cmdline,
660                         pass_data_thru, assuan_context,
661                         inq_needpin, &inqparm,
662                         pass_status_thru, assuan_context);
663   if (rc)
664     {
665       return unlock_scd (map_assuan_err (rc));
666     }
667
668   return unlock_scd (0);
669 }
670
671