* protect-tool.c: New option --enable-status-msg.
[gnupg.git] / sm / export.c
1 /* export.c
2  * Copyright (C) 2002, 2003, 2004 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 <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <unistd.h> 
27 #include <time.h>
28 #include <assert.h>
29 #include <signal.h>
30 #include <fcntl.h>
31 #include <sys/wait.h>
32
33 #include "gpgsm.h"
34 #include <gcrypt.h>
35 #include <ksba.h>
36
37 #include "keydb.h"
38 #include "i18n.h"
39
40 #ifdef _POSIX_OPEN_MAX
41 #define MAX_OPEN_FDS _POSIX_OPEN_MAX
42 #else
43 #define MAX_OPEN_FDS 20
44 #endif
45
46
47 /* A table to store a fingerprint as used in a duplicates table.  We
48    don't need to hash here because a fingerprint is alrady a perfect
49    hash value.  This we use the most significant bits to index the
50    table and then use a linked list for the overflow.  Possible
51    enhancement for very large number of certictates: Add a second
52    level table and then resort to a linked list. */
53 struct duptable_s
54 {
55   struct duptable_s *next;
56
57   /* Note that we only need to store 19 bytes because the first byte
58      is implictly given by the table index (we require at least 8
59      bits). */
60   unsigned char fpr[19];
61 };
62 typedef struct duptable_s *duptable_t;
63 #define DUPTABLE_BITS 12
64 #define DUPTABLE_SIZE (1 << DUPTABLE_BITS)
65
66
67 static void print_short_info (ksba_cert_t cert, FILE *fp);
68 static gpg_error_t export_p12 (const unsigned char *certimg, size_t certimglen,
69                                const char *prompt, const char *keygrip,
70                                FILE **retfp);
71
72
73 /* Create a table used to indetify duplicated certificates. */
74 static duptable_t *
75 create_duptable (void)
76 {
77   return xtrycalloc (DUPTABLE_SIZE, sizeof (duptable_t));
78 }
79
80 static void
81 destroy_duptable (duptable_t *table)
82 {
83   int idx;
84   duptable_t t, t2;
85
86   if (table)
87     {
88       for (idx=0; idx < DUPTABLE_SIZE; idx++) 
89         for (t = table[idx]; t; t = t2)
90           {
91             t2 = t->next;
92             xfree (t);
93           }
94       xfree (table);
95     }
96 }
97
98 /* Insert the 20 byte fingerprint FPR into TABLE.  Sets EXITS to true
99    if the fingerprint already exists in the table. */
100 static gpg_error_t
101 insert_duptable (duptable_t *table, unsigned char *fpr, int *exists)
102 {
103   size_t idx;
104   duptable_t t;
105   
106   *exists = 0;
107   idx = fpr[0];
108 #if DUPTABLE_BITS > 16 || DUPTABLE_BITS < 8
109 #error cannot handle a table larger than 16 bits or smaller than 8 bits
110 #elif DUPTABLE_BITS > 8
111   idx <<= (DUPTABLE_BITS - 8);  
112   idx |= (fpr[1] & ~(~0 << 4)); 
113 #endif  
114
115   for (t = table[idx]; t; t = t->next)
116     if (!memcmp (t->fpr, fpr+1, 19))
117       break;
118   if (t)
119     {
120       *exists = 1;
121       return 0;
122     }
123   /* Insert that fingerprint. */
124   t = xtrymalloc (sizeof *t);
125   if (!t)
126     return gpg_error_from_errno (errno);
127   memcpy (t->fpr, fpr+1, 19);
128   t->next = table[idx];
129   table[idx] = t;
130   return 0;
131 }
132
133
134
135
136 /* Export all certificates or just those given in NAMES. */
137 void
138 gpgsm_export (CTRL ctrl, STRLIST names, FILE *fp)
139 {
140   KEYDB_HANDLE hd = NULL;
141   KEYDB_SEARCH_DESC *desc = NULL;
142   int ndesc;
143   Base64Context b64writer = NULL;
144   ksba_writer_t writer;
145   STRLIST sl;
146   ksba_cert_t cert = NULL;
147   int rc=0;
148   int count = 0;
149   int i;
150   duptable_t *dtable;
151
152   
153   dtable = create_duptable ();
154   if (!dtable)
155     {
156       log_error ("creating duplicates table failed: %s\n", strerror (errno));
157       goto leave;
158     }
159
160   hd = keydb_new (0);
161   if (!hd)
162     {
163       log_error ("keydb_new failed\n");
164       goto leave;
165     }
166
167   if (!names)
168     ndesc = 1;
169   else
170     {
171       for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++) 
172         ;
173     }
174
175   desc = xtrycalloc (ndesc, sizeof *desc);
176   if (!ndesc)
177     {
178       log_error ("allocating memory for export failed: %s\n",
179                  gpg_strerror (OUT_OF_CORE (errno)));
180       goto leave;
181     }
182
183   if (!names)
184     desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
185   else 
186     {
187       for (ndesc=0, sl=names; sl; sl = sl->next) 
188         {
189           rc = keydb_classify_name (sl->d, desc+ndesc);
190           if (rc)
191             {
192               log_error ("key `%s' not found: %s\n",
193                          sl->d, gpg_strerror (rc));
194               rc = 0;
195             }
196           else
197             ndesc++;
198         }
199     }
200
201   /* If all specifications are done by fingerprint, we switch to
202      ephemeral mode so that _all_ currently available and matching
203      certificates are exported. 
204
205      fixme: we should in this case keep a list of certificates to
206      avoid accidential export of duplicate certificates. */
207   if (names && ndesc)
208     {
209       for (i=0; (i < ndesc
210                  && (desc[i].mode == KEYDB_SEARCH_MODE_FPR
211                      || desc[i].mode == KEYDB_SEARCH_MODE_FPR20
212                      || desc[i].mode == KEYDB_SEARCH_MODE_FPR16)); i++)
213         ;
214       if (i == ndesc)
215         keydb_set_ephemeral (hd, 1);
216     }
217       
218   while (!(rc = keydb_search (hd, desc, ndesc)))
219     {
220       unsigned char fpr[20];
221       int exists;
222
223       if (!names) 
224         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
225
226       rc = keydb_get_cert (hd, &cert);
227       if (rc) 
228         {
229           log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
230           goto leave;
231         }
232
233       gpgsm_get_fingerprint (cert, 0, fpr, NULL);
234       rc = insert_duptable (dtable, fpr, &exists);
235       if (rc)
236         {
237           log_error ("inserting into duplicates table fauiled: %s\n",
238                      gpg_strerror (rc));
239           goto leave;
240         }
241
242       if (!exists && count && !ctrl->create_pem)
243         {
244           log_info ("exporting more than one certificate "
245                     "is not possible in binary mode\n");
246           log_info ("ignoring other certificates\n");
247           break;
248         }
249
250       if (!exists)
251         {
252           const unsigned char *image;
253           size_t imagelen;
254
255           image = ksba_cert_get_image (cert, &imagelen);
256           if (!image)
257             {
258               log_error ("ksba_cert_get_image failed\n");
259               goto leave;
260             }
261
262
263           if (ctrl->create_pem)
264             {
265               if (count)
266                 putc ('\n', fp);
267               print_short_info (cert, fp);
268               putc ('\n', fp);
269             }
270           count++;
271
272           if (!b64writer)
273             {
274               ctrl->pem_name = "CERTIFICATE";
275               rc = gpgsm_create_writer (&b64writer, ctrl, fp, &writer);
276               if (rc)
277                 {
278                   log_error ("can't create writer: %s\n", gpg_strerror (rc));
279                   goto leave;
280                 }
281             }
282
283           rc = ksba_writer_write (writer, image, imagelen);
284           if (rc)
285             {
286               log_error ("write error: %s\n", gpg_strerror (rc));
287               goto leave;
288             }
289
290           if (ctrl->create_pem)
291             {
292               /* We want one certificate per PEM block */
293               rc = gpgsm_finish_writer (b64writer);
294               if (rc) 
295                 {
296                   log_error ("write failed: %s\n", gpg_strerror (rc));
297                   goto leave;
298                 }
299               gpgsm_destroy_writer (b64writer);
300               b64writer = NULL;
301             }
302         }
303
304       ksba_cert_release (cert); 
305       cert = NULL;
306     }
307   if (rc && rc != -1)
308     log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
309   else if (b64writer)
310     {
311       rc = gpgsm_finish_writer (b64writer);
312       if (rc) 
313         {
314           log_error ("write failed: %s\n", gpg_strerror (rc));
315           goto leave;
316         }
317     }
318   
319  leave:
320   gpgsm_destroy_writer (b64writer);
321   ksba_cert_release (cert);
322   xfree (desc);
323   keydb_release (hd);
324   destroy_duptable (dtable);
325 }
326
327
328 /* Export a certificates and its private key. */
329 void
330 gpgsm_p12_export (ctrl_t ctrl, const char *name, FILE *fp)
331 {
332   KEYDB_HANDLE hd;
333   KEYDB_SEARCH_DESC *desc = NULL;
334   Base64Context b64writer = NULL;
335   ksba_writer_t writer;
336   ksba_cert_t cert = NULL;
337   int rc=0;
338   const unsigned char *image;
339   size_t imagelen;
340   char *keygrip = NULL;
341   char *prompt;
342   char buffer[1024];
343   int  nread;
344   FILE *datafp = NULL;
345
346
347   hd = keydb_new (0);
348   if (!hd)
349     {
350       log_error ("keydb_new failed\n");
351       goto leave;
352     }
353
354   desc = xtrycalloc (1, sizeof *desc);
355   if (!desc)
356     {
357       log_error ("allocating memory for export failed: %s\n",
358                  gpg_strerror (OUT_OF_CORE (errno)));
359       goto leave;
360     }
361
362   rc = keydb_classify_name (name, desc);
363   if (rc)
364     {
365       log_error ("key `%s' not found: %s\n",
366                  name, gpg_strerror (rc));
367       goto leave;
368     }
369
370   /* Lookup the certificate an make sure that it is unique. */
371   rc = keydb_search (hd, desc, 1);
372   if (!rc)
373     {
374       rc = keydb_get_cert (hd, &cert);
375       if (rc) 
376         {
377           log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
378           goto leave;
379         }
380       
381       rc = keydb_search (hd, desc, 1);
382       if (!rc)
383         rc = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
384       else if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
385         rc = 0;
386       if (rc)
387         {
388           log_error ("key `%s' not found: %s\n",
389                      name, gpg_strerror (rc));
390           goto leave;
391         }
392     }
393       
394   keygrip = gpgsm_get_keygrip_hexstring (cert);
395   if (!keygrip || gpgsm_agent_havekey (ctrl, keygrip))
396     {
397       /* Note, that the !keygrip case indicates a bad certificate. */
398       rc = gpg_error (GPG_ERR_NO_SECKEY);
399       log_error ("can't export key `%s': %s\n", name, gpg_strerror (rc));
400       goto leave;
401     }
402   
403   image = ksba_cert_get_image (cert, &imagelen);
404   if (!image)
405     {
406       log_error ("ksba_cert_get_image failed\n");
407       goto leave;
408     }
409
410   if (ctrl->create_pem)
411     {
412       print_short_info (cert, fp);
413       putc ('\n', fp);
414     }
415
416   ctrl->pem_name = "PKCS12";
417   rc = gpgsm_create_writer (&b64writer, ctrl, fp, &writer);
418   if (rc)
419     {
420       log_error ("can't create writer: %s\n", gpg_strerror (rc));
421       goto leave;
422     }
423
424
425   prompt = gpgsm_format_keydesc (cert);
426   rc = export_p12 (image, imagelen, prompt, keygrip, &datafp);
427   xfree (prompt);
428   if (rc)
429     goto leave;
430   rewind (datafp);
431   while ( (nread = fread (buffer, 1, sizeof buffer, datafp)) > 0 )
432     if ((rc = ksba_writer_write (writer, buffer, nread)))
433       {
434         log_error ("write failed: %s\n", gpg_strerror (rc));
435         goto leave;
436       }
437   if (ferror (datafp))
438     {
439       rc = gpg_error_from_errno (rc);
440       log_error ("error reading temporary file: %s\n", gpg_strerror (rc));
441       goto leave;
442     }
443
444   if (ctrl->create_pem)
445     {
446       /* We want one certificate per PEM block */
447       rc = gpgsm_finish_writer (b64writer);
448       if (rc) 
449         {
450           log_error ("write failed: %s\n", gpg_strerror (rc));
451           goto leave;
452         }
453       gpgsm_destroy_writer (b64writer);
454       b64writer = NULL;
455     }
456   
457   ksba_cert_release (cert); 
458   cert = NULL;
459
460  leave:
461   if (datafp)
462     fclose (datafp);
463   gpgsm_destroy_writer (b64writer);
464   ksba_cert_release (cert);
465   xfree (desc);
466   keydb_release (hd);
467 }
468
469
470 /* Print some info about the certifciate CERT to FP */
471 static void
472 print_short_info (ksba_cert_t cert, FILE *fp)
473 {
474   char *p;
475   ksba_sexp_t sexp;
476   int idx;
477
478   for (idx=0; (p = ksba_cert_get_issuer (cert, idx)); idx++)
479     {
480       fputs (!idx?   "Issuer ...: "
481                  : "\n   aka ...: ", fp); 
482       gpgsm_print_name (fp, p);
483       xfree (p);
484     }
485   putc ('\n', fp);
486
487   fputs ("Serial ...: ", fp); 
488   sexp = ksba_cert_get_serial (cert);
489   if (sexp)
490     {
491       int len;
492       const unsigned char *s = sexp;
493       
494       if (*s == '(')
495         {
496           s++;
497           for (len=0; *s && *s != ':' && digitp (s); s++)
498             len = len*10 + atoi_1 (s);
499           if (*s == ':')
500             for (s++; len; len--, s++)
501               fprintf (fp, "%02X", *s);
502         }
503       xfree (sexp);
504     }
505   putc ('\n', fp);
506
507   for (idx=0; (p = ksba_cert_get_subject (cert, idx)); idx++)
508     {
509       fputs (!idx?   "Subject ..: "
510                  : "\n    aka ..: ", fp); 
511       gpgsm_print_name (fp, p);
512       xfree (p);
513     }
514   putc ('\n', fp);
515 }
516
517
518 static gpg_error_t
519 popen_protect_tool (const char *pgmname,
520                     FILE *infile, FILE *outfile, FILE **statusfile, 
521                     const char *prompt, const char *keygrip,
522                     pid_t *pid)
523 {
524   gpg_error_t err;
525   int fd, fdout, rp[2];
526   int n, i;
527
528   fflush (infile);
529   rewind (infile);
530   fd = fileno (infile);
531   fdout = fileno (outfile);
532   if (fd == -1 || fdout == -1)
533     log_fatal ("no file descriptor for temporary file: %s\n",
534                strerror (errno));
535
536   /* Now start the protect-tool. */
537   if (pipe (rp) == -1)
538     {
539       err = gpg_error_from_errno (errno);
540       log_error (_("error creating a pipe: %s\n"), strerror (errno));
541       return err;
542     }
543       
544   *pid = fork ();
545   if (*pid == -1)
546     {
547       err = gpg_error_from_errno (errno);
548       log_error (_("error forking process: %s\n"), strerror (errno));
549       close (rp[0]);
550       close (rp[1]);
551       return err;
552     }
553
554   if (!*pid)
555     { /* Child. */
556       const char *arg0;
557
558       arg0 = strrchr (pgmname, '/');
559       if (arg0)
560         arg0++;
561       else
562         arg0 = pgmname;
563
564       /* Connect the infile to stdin. */
565       if (fd != 0 && dup2 (fd, 0) == -1)
566         log_fatal ("dup2 stdin failed: %s\n", strerror (errno));
567
568       /* Connect the outfile to stdout. */
569       if (fdout != 1 && dup2 (fdout, 1) == -1)
570         log_fatal ("dup2 stdout failed: %s\n", strerror (errno));
571       
572       /* Connect stderr to our pipe. */
573       if (rp[1] != 2 && dup2 (rp[1], 2) == -1)
574         log_fatal ("dup2 stderr failed: %s\n", strerror (errno));
575
576       /* Close all other files. */
577       n = sysconf (_SC_OPEN_MAX);
578       if (n < 0)
579         n = MAX_OPEN_FDS;
580       for (i=3; i < n; i++)
581         close(i);
582       errno = 0;
583
584       setup_pinentry_env ();
585
586       execlp (pgmname, arg0,
587               "--homedir", opt.homedir,
588               "--p12-export",
589               "--prompt", prompt?prompt:"", 
590               "--",
591               keygrip,
592               NULL);
593       /* No way to print anything, as we have closed all streams. */
594       _exit (31);
595     }
596
597   /* Parent. */
598   close (rp[1]);
599   *statusfile = fdopen (rp[0], "r");
600   if (!*statusfile)
601     {
602       err = gpg_error_from_errno (errno);
603       log_error ("can't fdopen pipe for reading: %s", strerror (errno));
604       kill (*pid, SIGTERM);
605       return err;
606     }
607
608   return 0;
609 }
610
611
612 static gpg_error_t
613 export_p12 (const unsigned char *certimg, size_t certimglen,
614             const char *prompt, const char *keygrip,
615             FILE **retfp)
616 {
617   const char *pgmname;
618   gpg_error_t err = 0, child_err = 0;
619   int i, c, cont_line;
620   unsigned int pos;
621   FILE *infp = NULL, *outfp = NULL, *fp = NULL;
622   char buffer[1024];
623   pid_t pid = -1;
624
625   if (!opt.protect_tool_program || !*opt.protect_tool_program)
626     pgmname = GNUPG_DEFAULT_PROTECT_TOOL;
627   else
628     pgmname = opt.protect_tool_program;
629
630   infp = tmpfile ();
631   if (!infp)
632     {
633       err = gpg_error_from_errno (errno);
634       log_error (_("error creating temporary file: %s\n"), strerror (errno));
635       goto cleanup;
636     }
637
638   if (fwrite (certimg, certimglen, 1, infp) != 1)
639     {
640       err = gpg_error_from_errno (errno);
641       log_error (_("error writing to temporary file: %s\n"),
642                  strerror (errno));
643       goto cleanup;
644     }
645
646   outfp = tmpfile ();
647   if (!outfp)
648     {
649       err = gpg_error_from_errno (errno);
650       log_error (_("error creating temporary file: %s\n"), strerror (errno));
651       goto cleanup;
652     }
653
654   err = popen_protect_tool (pgmname, infp, outfp, &fp, prompt, keygrip, &pid);
655   if (err)
656     {
657       pid = -1;
658       goto cleanup;
659     }
660   fclose (infp);
661   infp = NULL;
662
663   /* Read stderr of the protect tool. */
664   pos = 0;
665   cont_line = 0;
666   while ((c=getc (fp)) != EOF)
667     {
668       /* fixme: We could here grep for status information of the
669          protect tool to figure out better error codes for
670          CHILD_ERR. */
671       buffer[pos++] = c;
672       if (pos >= 5 /*sizeof buffer - 1*/ || c == '\n')
673         {
674           buffer[pos - (c == '\n')] = 0;
675           if (cont_line)
676             log_printf ("%s", buffer);
677           else
678             log_info ("%s", buffer);
679           pos = 0;
680           cont_line = (c != '\n');
681         }
682     }
683
684   if (pos)
685     {
686       buffer[pos] = 0;
687       if (cont_line)
688         log_printf ("%s\n", buffer);
689       else
690         log_info ("%s\n", buffer);
691     }
692   else if (cont_line)
693     log_printf ("\n");
694
695   /* If we found no error in the output of the child, setup a suitable
696      error code, which will later be reset if the exit status of the
697      child is 0. */
698   if (!child_err)
699     child_err = gpg_error (GPG_ERR_DECRYPT_FAILED);
700
701  cleanup:
702   if (infp)
703     fclose (infp);
704   if (fp)
705     fclose (fp);
706   if (pid != -1)
707     {
708       int status;
709
710       while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR)
711         ;
712       if (i == -1)
713         log_error (_("waiting for protect-tools to terminate failed: %s\n"),
714                    strerror (errno));
715       else if (WIFEXITED (status) && WEXITSTATUS (status) == 31)
716         log_error (_("error running `%s': probably not installed\n"), pgmname);
717       else if (WIFEXITED (status) && WEXITSTATUS (status))
718         log_error (_("error running `%s': exit status %d\n"), pgmname,
719                      WEXITSTATUS (status));
720       else if (!WIFEXITED (status))
721         log_error (_("error running `%s': terminated\n"), pgmname);
722       else 
723         child_err = 0;
724     }
725   if (!err)
726     err = child_err;
727   if (err)
728     {
729       if (outfp)
730         fclose (outfp);
731     }
732   else
733     *retfp = outfp;
734   return err;
735 }
736