(create_duptable, destroy_duptable)
[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 tem to store a fingerprint 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
109 #error cannot handle a table larger than 16 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)
243         {
244           const unsigned char *image;
245           size_t imagelen;
246
247           image = ksba_cert_get_image (cert, &imagelen);
248           if (!image)
249             {
250               log_error ("ksba_cert_get_image failed\n");
251               goto leave;
252             }
253
254
255           if (ctrl->create_pem)
256             {
257               if (count)
258                 putc ('\n', fp);
259               print_short_info (cert, fp);
260               putc ('\n', fp);
261             }
262           count++;
263
264           if (!b64writer)
265             {
266               ctrl->pem_name = "CERTIFICATE";
267               rc = gpgsm_create_writer (&b64writer, ctrl, fp, &writer);
268               if (rc)
269                 {
270                   log_error ("can't create writer: %s\n", gpg_strerror (rc));
271                   goto leave;
272                 }
273             }
274
275           rc = ksba_writer_write (writer, image, imagelen);
276           if (rc)
277             {
278               log_error ("write error: %s\n", gpg_strerror (rc));
279               goto leave;
280             }
281
282           if (ctrl->create_pem)
283             {
284               /* We want one certificate per PEM block */
285               rc = gpgsm_finish_writer (b64writer);
286               if (rc) 
287                 {
288                   log_error ("write failed: %s\n", gpg_strerror (rc));
289                   goto leave;
290                 }
291               gpgsm_destroy_writer (b64writer);
292               b64writer = NULL;
293             }
294         }
295
296       ksba_cert_release (cert); 
297       cert = NULL;
298     }
299   if (rc && rc != -1)
300     log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
301   else if (b64writer)
302     {
303       rc = gpgsm_finish_writer (b64writer);
304       if (rc) 
305         {
306           log_error ("write failed: %s\n", gpg_strerror (rc));
307           goto leave;
308         }
309     }
310   
311  leave:
312   gpgsm_destroy_writer (b64writer);
313   ksba_cert_release (cert);
314   xfree (desc);
315   keydb_release (hd);
316   destroy_duptable (dtable);
317 }
318
319
320 /* Export a certificates and its private key. */
321 void
322 gpgsm_p12_export (ctrl_t ctrl, const char *name, FILE *fp)
323 {
324   KEYDB_HANDLE hd;
325   KEYDB_SEARCH_DESC *desc = NULL;
326   Base64Context b64writer = NULL;
327   ksba_writer_t writer;
328   ksba_cert_t cert = NULL;
329   int rc=0;
330   const unsigned char *image;
331   size_t imagelen;
332   char *keygrip = NULL;
333   char *prompt;
334   char buffer[1024];
335   int  nread;
336   FILE *datafp = NULL;
337
338
339   hd = keydb_new (0);
340   if (!hd)
341     {
342       log_error ("keydb_new failed\n");
343       goto leave;
344     }
345
346   desc = xtrycalloc (1, sizeof *desc);
347   if (!desc)
348     {
349       log_error ("allocating memory for export failed: %s\n",
350                  gpg_strerror (OUT_OF_CORE (errno)));
351       goto leave;
352     }
353
354   rc = keydb_classify_name (name, desc);
355   if (rc)
356     {
357       log_error ("key `%s' not found: %s\n",
358                  name, gpg_strerror (rc));
359       goto leave;
360     }
361
362   /* Lookup the certificate an make sure that it is unique. */
363   rc = keydb_search (hd, desc, 1);
364   if (!rc)
365     {
366       rc = keydb_get_cert (hd, &cert);
367       if (rc) 
368         {
369           log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
370           goto leave;
371         }
372       
373       rc = keydb_search (hd, desc, 1);
374       if (!rc)
375         rc = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
376       else if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
377         rc = 0;
378       if (rc)
379         {
380           log_error ("key `%s' not found: %s\n",
381                      name, gpg_strerror (rc));
382           goto leave;
383         }
384     }
385       
386   keygrip = gpgsm_get_keygrip_hexstring (cert);
387   if (!keygrip || gpgsm_agent_havekey (keygrip))
388     {
389       /* Note, that the !keygrip case indicates a bad certificate. */
390       rc = gpg_error (GPG_ERR_NO_SECKEY);
391       log_error ("can't export key `%s': %s\n", name, gpg_strerror (rc));
392       goto leave;
393     }
394   
395   image = ksba_cert_get_image (cert, &imagelen);
396   if (!image)
397     {
398       log_error ("ksba_cert_get_image failed\n");
399       goto leave;
400     }
401
402   if (ctrl->create_pem)
403     {
404       print_short_info (cert, fp);
405       putc ('\n', fp);
406     }
407
408   ctrl->pem_name = "PKCS12";
409   rc = gpgsm_create_writer (&b64writer, ctrl, fp, &writer);
410   if (rc)
411     {
412       log_error ("can't create writer: %s\n", gpg_strerror (rc));
413       goto leave;
414     }
415
416
417   prompt = gpgsm_format_keydesc (cert);
418   rc = export_p12 (image, imagelen, prompt, keygrip, &datafp);
419   xfree (prompt);
420   if (rc)
421     goto leave;
422   rewind (datafp);
423   while ( (nread = fread (buffer, 1, sizeof buffer, datafp)) > 0 )
424     if ((rc = ksba_writer_write (writer, buffer, nread)))
425       {
426         log_error ("write failed: %s\n", gpg_strerror (rc));
427         goto leave;
428       }
429   if (ferror (datafp))
430     {
431       rc = gpg_error_from_errno (rc);
432       log_error ("error reading temporary file: %s\n", gpg_strerror (rc));
433       goto leave;
434     }
435
436   if (ctrl->create_pem)
437     {
438       /* We want one certificate per PEM block */
439       rc = gpgsm_finish_writer (b64writer);
440       if (rc) 
441         {
442           log_error ("write failed: %s\n", gpg_strerror (rc));
443           goto leave;
444         }
445       gpgsm_destroy_writer (b64writer);
446       b64writer = NULL;
447     }
448   
449   ksba_cert_release (cert); 
450   cert = NULL;
451
452  leave:
453   if (datafp)
454     fclose (datafp);
455   gpgsm_destroy_writer (b64writer);
456   ksba_cert_release (cert);
457   xfree (desc);
458   keydb_release (hd);
459 }
460
461
462 /* Print some info about the certifciate CERT to FP */
463 static void
464 print_short_info (ksba_cert_t cert, FILE *fp)
465 {
466   char *p;
467   ksba_sexp_t sexp;
468   int idx;
469
470   for (idx=0; (p = ksba_cert_get_issuer (cert, idx)); idx++)
471     {
472       fputs (!idx?   "Issuer ...: "
473                  : "\n   aka ...: ", fp); 
474       gpgsm_print_name (fp, p);
475       xfree (p);
476     }
477   putc ('\n', fp);
478
479   fputs ("Serial ...: ", fp); 
480   sexp = ksba_cert_get_serial (cert);
481   if (sexp)
482     {
483       int len;
484       const unsigned char *s = sexp;
485       
486       if (*s == '(')
487         {
488           s++;
489           for (len=0; *s && *s != ':' && digitp (s); s++)
490             len = len*10 + atoi_1 (s);
491           if (*s == ':')
492             for (s++; len; len--, s++)
493               fprintf (fp, "%02X", *s);
494         }
495       xfree (sexp);
496     }
497   putc ('\n', fp);
498
499   for (idx=0; (p = ksba_cert_get_subject (cert, idx)); idx++)
500     {
501       fputs (!idx?   "Subject ..: "
502                  : "\n    aka ..: ", fp); 
503       gpgsm_print_name (fp, p);
504       xfree (p);
505     }
506   putc ('\n', fp);
507 }
508
509
510 static gpg_error_t
511 popen_protect_tool (const char *pgmname,
512                     FILE *infile, FILE *outfile, FILE **statusfile, 
513                     const char *prompt, const char *keygrip,
514                     pid_t *pid)
515 {
516   gpg_error_t err;
517   int fd, fdout, rp[2];
518   int n, i;
519
520   fflush (infile);
521   rewind (infile);
522   fd = fileno (infile);
523   fdout = fileno (outfile);
524   if (fd == -1 || fdout == -1)
525     log_fatal ("no file descriptor for temporary file: %s\n",
526                strerror (errno));
527
528   /* Now start the protect-tool. */
529   if (pipe (rp) == -1)
530     {
531       err = gpg_error_from_errno (errno);
532       log_error (_("error creating a pipe: %s\n"), strerror (errno));
533       return err;
534     }
535       
536   *pid = fork ();
537   if (*pid == -1)
538     {
539       err = gpg_error_from_errno (errno);
540       log_error (_("error forking process: %s\n"), strerror (errno));
541       close (rp[0]);
542       close (rp[1]);
543       return err;
544     }
545
546   if (!*pid)
547     { /* Child. */
548       const char *arg0;
549
550       arg0 = strrchr (pgmname, '/');
551       if (arg0)
552         arg0++;
553       else
554         arg0 = pgmname;
555
556       /* Connect the infile to stdin. */
557       if (fd != 0 && dup2 (fd, 0) == -1)
558         log_fatal ("dup2 stdin failed: %s\n", strerror (errno));
559
560       /* Connect the outfile to stdout. */
561       if (fdout != 1 && dup2 (fdout, 1) == -1)
562         log_fatal ("dup2 stdout failed: %s\n", strerror (errno));
563       
564       /* Connect stderr to our pipe. */
565       if (rp[1] != 2 && dup2 (rp[1], 2) == -1)
566         log_fatal ("dup2 stderr failed: %s\n", strerror (errno));
567
568       /* Close all other files. */
569       n = sysconf (_SC_OPEN_MAX);
570       if (n < 0)
571         n = MAX_OPEN_FDS;
572       for (i=3; i < n; i++)
573         close(i);
574       errno = 0;
575
576       execlp (pgmname, arg0,
577               "--homedir", opt.homedir,
578               "--p12-export",
579               "--prompt", prompt?prompt:"", 
580               "--",
581               keygrip,
582               NULL);
583       /* No way to print anything, as we have closed all streams. */
584       _exit (31);
585     }
586
587   /* Parent. */
588   close (rp[1]);
589   *statusfile = fdopen (rp[0], "r");
590   if (!*statusfile)
591     {
592       err = gpg_error_from_errno (errno);
593       log_error ("can't fdopen pipe for reading: %s", strerror (errno));
594       kill (*pid, SIGTERM);
595       return err;
596     }
597
598   return 0;
599 }
600
601
602 static gpg_error_t
603 export_p12 (const unsigned char *certimg, size_t certimglen,
604             const char *prompt, const char *keygrip,
605             FILE **retfp)
606 {
607   const char *pgmname;
608   gpg_error_t err = 0, child_err = 0;
609   int i, c, cont_line;
610   unsigned int pos;
611   FILE *infp = NULL, *outfp = NULL, *fp = NULL;
612   char buffer[1024];
613   pid_t pid = -1;
614
615   if (!opt.protect_tool_program || !*opt.protect_tool_program)
616     pgmname = GNUPG_DEFAULT_PROTECT_TOOL;
617   else
618     pgmname = opt.protect_tool_program;
619
620   infp = tmpfile ();
621   if (!infp)
622     {
623       err = gpg_error_from_errno (errno);
624       log_error (_("error creating temporary file: %s\n"), strerror (errno));
625       goto cleanup;
626     }
627
628   if (fwrite (certimg, certimglen, 1, infp) != 1)
629     {
630       err = gpg_error_from_errno (errno);
631       log_error (_("error writing to temporary file: %s\n"),
632                  strerror (errno));
633       goto cleanup;
634     }
635
636   outfp = tmpfile ();
637   if (!outfp)
638     {
639       err = gpg_error_from_errno (errno);
640       log_error (_("error creating temporary file: %s\n"), strerror (errno));
641       goto cleanup;
642     }
643
644   err = popen_protect_tool (pgmname, infp, outfp, &fp, prompt, keygrip, &pid);
645   if (err)
646     {
647       pid = -1;
648       goto cleanup;
649     }
650   fclose (infp);
651   infp = NULL;
652
653   /* Read stderr of the protect tool. */
654   pos = 0;
655   cont_line = 0;
656   while ((c=getc (fp)) != EOF)
657     {
658       /* fixme: We could here grep for status information of the
659          protect tool to figure out better error codes for
660          CHILD_ERR. */
661       buffer[pos++] = c;
662       if (pos >= 5 /*sizeof buffer - 1*/ || c == '\n')
663         {
664           buffer[pos - (c == '\n')] = 0;
665           if (cont_line)
666             log_printf ("%s", buffer);
667           else
668             log_info ("%s", buffer);
669           pos = 0;
670           cont_line = (c != '\n');
671         }
672     }
673
674   if (pos)
675     {
676       buffer[pos] = 0;
677       if (cont_line)
678         log_printf ("%s\n", buffer);
679       else
680         log_info ("%s\n", buffer);
681     }
682   else if (cont_line)
683     log_printf ("\n");
684
685   /* If we found no error in the output of the child, setup a suitable
686      error code, which will later be reset if the exit status of the
687      child is 0. */
688   if (!child_err)
689     child_err = gpg_error (GPG_ERR_DECRYPT_FAILED);
690
691  cleanup:
692   if (infp)
693     fclose (infp);
694   if (fp)
695     fclose (fp);
696   if (pid != -1)
697     {
698       int status;
699
700       while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR)
701         ;
702       if (i == -1)
703         log_error (_("waiting for protect-tools to terminate failed: %s\n"),
704                    strerror (errno));
705       else if (WIFEXITED (status) && WEXITSTATUS (status) == 31)
706         log_error (_("error running `%s': probably not installed\n"), pgmname);
707       else if (WIFEXITED (status) && WEXITSTATUS (status))
708         log_error (_("error running `%s': exit status %d\n"), pgmname,
709                      WEXITSTATUS (status));
710       else if (!WIFEXITED (status))
711         log_error (_("error running `%s': terminated\n"), pgmname);
712       else 
713         child_err = 0;
714     }
715   if (!err)
716     err = child_err;
717   if (err)
718     {
719       if (outfp)
720         fclose (outfp);
721     }
722   else
723     *retfp = outfp;
724   return err;
725 }
726