* protect-tool.c: New options --have-cert and --prompt.
[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
48 static void print_short_info (ksba_cert_t cert, FILE *fp);
49 static gpg_error_t export_p12 (const unsigned char *certimg, size_t certimglen,
50                                const char *prompt, const char *keygrip,
51                                FILE **retfp);
52
53
54
55 /* Export all certificates or just those given in NAMES. */
56 void
57 gpgsm_export (CTRL ctrl, STRLIST names, FILE *fp)
58 {
59   KEYDB_HANDLE hd;
60   KEYDB_SEARCH_DESC *desc = NULL;
61   int ndesc;
62   Base64Context b64writer = NULL;
63   ksba_writer_t writer;
64   STRLIST sl;
65   ksba_cert_t cert = NULL;
66   int rc=0;
67   int count = 0;
68   int i;
69
70   hd = keydb_new (0);
71   if (!hd)
72     {
73       log_error ("keydb_new failed\n");
74       goto leave;
75     }
76
77   if (!names)
78     ndesc = 1;
79   else
80     {
81       for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++) 
82         ;
83     }
84
85   desc = xtrycalloc (ndesc, sizeof *desc);
86   if (!ndesc)
87     {
88       log_error ("allocating memory for export failed: %s\n",
89                  gpg_strerror (OUT_OF_CORE (errno)));
90       goto leave;
91     }
92
93   if (!names)
94     desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
95   else 
96     {
97       for (ndesc=0, sl=names; sl; sl = sl->next) 
98         {
99           rc = keydb_classify_name (sl->d, desc+ndesc);
100           if (rc)
101             {
102               log_error ("key `%s' not found: %s\n",
103                          sl->d, gpg_strerror (rc));
104               rc = 0;
105             }
106           else
107             ndesc++;
108         }
109     }
110
111   /* If all specifications are done by fingerprint, we switch to
112      ephemeral mode so that _all_ currently available and matching
113      certificates are exported. 
114
115      fixme: we should in this case keep a list of certificates to
116      avoid accidential export of duplicate certificates. */
117   if (names && ndesc)
118     {
119       for (i=0; (i < ndesc
120                  && (desc[i].mode == KEYDB_SEARCH_MODE_FPR
121                      || desc[i].mode == KEYDB_SEARCH_MODE_FPR20
122                      || desc[i].mode == KEYDB_SEARCH_MODE_FPR16)); i++)
123         ;
124       if (i == ndesc)
125         keydb_set_ephemeral (hd, 1);
126     }
127       
128   while (!(rc = keydb_search (hd, desc, ndesc)))
129     {
130       const unsigned char *image;
131       size_t imagelen;
132
133       if (!names) 
134         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
135
136       rc = keydb_get_cert (hd, &cert);
137       if (rc) 
138         {
139           log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
140           goto leave;
141         }
142
143       image = ksba_cert_get_image (cert, &imagelen);
144       if (!image)
145         {
146           log_error ("ksba_cert_get_image failed\n");
147           goto leave;
148         }
149
150       if (ctrl->create_pem)
151         {
152           if (count)
153             putc ('\n', fp);
154           print_short_info (cert, fp);
155           putc ('\n', fp);
156         }
157       count++;
158
159       if (!b64writer)
160         {
161           ctrl->pem_name = "CERTIFICATE";
162           rc = gpgsm_create_writer (&b64writer, ctrl, fp, &writer);
163           if (rc)
164             {
165               log_error ("can't create writer: %s\n", gpg_strerror (rc));
166               goto leave;
167             }
168         }
169
170       rc = ksba_writer_write (writer, image, imagelen);
171       if (rc)
172         {
173           log_error ("write error: %s\n", gpg_strerror (rc));
174           goto leave;
175         }
176
177       if (ctrl->create_pem)
178         {
179           /* We want one certificate per PEM block */
180           rc = gpgsm_finish_writer (b64writer);
181           if (rc) 
182             {
183               log_error ("write failed: %s\n", gpg_strerror (rc));
184               goto leave;
185             }
186           gpgsm_destroy_writer (b64writer);
187           b64writer = NULL;
188         }
189       
190       ksba_cert_release (cert); 
191       cert = NULL;
192     }
193   if (rc && rc != -1)
194     log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
195   else if (b64writer)
196     {
197       rc = gpgsm_finish_writer (b64writer);
198       if (rc) 
199         {
200           log_error ("write failed: %s\n", gpg_strerror (rc));
201           goto leave;
202         }
203     }
204   
205  leave:
206   gpgsm_destroy_writer (b64writer);
207   ksba_cert_release (cert);
208   xfree (desc);
209   keydb_release (hd);
210 }
211
212
213 /* Export a certificates and its private key. */
214 void
215 gpgsm_p12_export (ctrl_t ctrl, const char *name, FILE *fp)
216 {
217   KEYDB_HANDLE hd;
218   KEYDB_SEARCH_DESC *desc = NULL;
219   Base64Context b64writer = NULL;
220   ksba_writer_t writer;
221   ksba_cert_t cert = NULL;
222   int rc=0;
223   const unsigned char *image;
224   size_t imagelen;
225   char *keygrip = NULL;
226   char *prompt;
227   char buffer[1024];
228   int  nread;
229   FILE *datafp = NULL;
230
231   hd = keydb_new (0);
232   if (!hd)
233     {
234       log_error ("keydb_new failed\n");
235       goto leave;
236     }
237
238   desc = xtrycalloc (1, sizeof *desc);
239   if (!desc)
240     {
241       log_error ("allocating memory for export failed: %s\n",
242                  gpg_strerror (OUT_OF_CORE (errno)));
243       goto leave;
244     }
245
246   rc = keydb_classify_name (name, desc);
247   if (rc)
248     {
249       log_error ("key `%s' not found: %s\n",
250                  name, gpg_strerror (rc));
251       goto leave;
252     }
253
254   /* Lookup the certificate an make sure that it is unique. */
255   rc = keydb_search (hd, desc, 1);
256   if (!rc)
257     {
258       rc = keydb_get_cert (hd, &cert);
259       if (rc) 
260         {
261           log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
262           goto leave;
263         }
264       
265       rc = keydb_search (hd, desc, 1);
266       if (!rc)
267         rc = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
268       else if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
269         rc = 0;
270       if (rc)
271         {
272           log_error ("key `%s' not found: %s\n",
273                      name, gpg_strerror (rc));
274           goto leave;
275         }
276     }
277       
278   keygrip = gpgsm_get_keygrip_hexstring (cert);
279   if (!keygrip || gpgsm_agent_havekey (keygrip))
280     {
281       /* Note, that the !keygrip case indicates a bad certificate. */
282       rc = gpg_error (GPG_ERR_NO_SECKEY);
283       log_error ("can't export key `%s': %s\n", name, gpg_strerror (rc));
284       goto leave;
285     }
286   
287   image = ksba_cert_get_image (cert, &imagelen);
288   if (!image)
289     {
290       log_error ("ksba_cert_get_image failed\n");
291       goto leave;
292     }
293
294   if (ctrl->create_pem)
295     {
296       print_short_info (cert, fp);
297       putc ('\n', fp);
298     }
299
300   ctrl->pem_name = "PKCS12";
301   rc = gpgsm_create_writer (&b64writer, ctrl, fp, &writer);
302   if (rc)
303     {
304       log_error ("can't create writer: %s\n", gpg_strerror (rc));
305       goto leave;
306     }
307
308
309   prompt = gpgsm_format_keydesc (cert);
310   rc = export_p12 (image, imagelen, prompt, keygrip, &datafp);
311   xfree (prompt);
312   if (rc)
313     goto leave;
314   rewind (datafp);
315   while ( (nread = fread (buffer, 1, sizeof buffer, datafp)) > 0 )
316     if ((rc = ksba_writer_write (writer, buffer, nread)))
317       {
318         log_error ("write failed: %s\n", gpg_strerror (rc));
319         goto leave;
320       }
321   if (ferror (datafp))
322     {
323       rc = gpg_error_from_errno (rc);
324       log_error ("error reading temporary file: %s\n", gpg_strerror (rc));
325       goto leave;
326     }
327
328   if (ctrl->create_pem)
329     {
330       /* We want one certificate per PEM block */
331       rc = gpgsm_finish_writer (b64writer);
332       if (rc) 
333         {
334           log_error ("write failed: %s\n", gpg_strerror (rc));
335           goto leave;
336         }
337       gpgsm_destroy_writer (b64writer);
338       b64writer = NULL;
339     }
340   
341   ksba_cert_release (cert); 
342   cert = NULL;
343
344  leave:
345   if (datafp)
346     fclose (datafp);
347   gpgsm_destroy_writer (b64writer);
348   ksba_cert_release (cert);
349   xfree (desc);
350   keydb_release (hd);
351 }
352
353
354 /* Print some info about the certifciate CERT to FP */
355 static void
356 print_short_info (ksba_cert_t cert, FILE *fp)
357 {
358   char *p;
359   ksba_sexp_t sexp;
360   int idx;
361
362   for (idx=0; (p = ksba_cert_get_issuer (cert, idx)); idx++)
363     {
364       fputs (!idx?   "Issuer ...: "
365                  : "\n   aka ...: ", fp); 
366       gpgsm_print_name (fp, p);
367       xfree (p);
368     }
369   putc ('\n', fp);
370
371   fputs ("Serial ...: ", fp); 
372   sexp = ksba_cert_get_serial (cert);
373   if (sexp)
374     {
375       int len;
376       const unsigned char *s = sexp;
377       
378       if (*s == '(')
379         {
380           s++;
381           for (len=0; *s && *s != ':' && digitp (s); s++)
382             len = len*10 + atoi_1 (s);
383           if (*s == ':')
384             for (s++; len; len--, s++)
385               fprintf (fp, "%02X", *s);
386         }
387       xfree (sexp);
388     }
389   putc ('\n', fp);
390
391   for (idx=0; (p = ksba_cert_get_subject (cert, idx)); idx++)
392     {
393       fputs (!idx?   "Subject ..: "
394                  : "\n    aka ..: ", fp); 
395       gpgsm_print_name (fp, p);
396       xfree (p);
397     }
398   putc ('\n', fp);
399 }
400
401
402 static gpg_error_t
403 popen_protect_tool (const char *pgmname,
404                     FILE *infile, FILE *outfile, FILE **statusfile, 
405                     const char *prompt, const char *keygrip,
406                     pid_t *pid)
407 {
408   gpg_error_t err;
409   int fd, fdout, rp[2];
410   int n, i;
411
412   fflush (infile);
413   rewind (infile);
414   fd = fileno (infile);
415   fdout = fileno (outfile);
416   if (fd == -1 || fdout == -1)
417     log_fatal ("no file descriptor for temporary file: %s\n",
418                strerror (errno));
419
420   /* Now start the protect-tool. */
421   if (pipe (rp) == -1)
422     {
423       err = gpg_error_from_errno (errno);
424       log_error (_("error creating a pipe: %s\n"), strerror (errno));
425       return err;
426     }
427       
428   *pid = fork ();
429   if (*pid == -1)
430     {
431       err = gpg_error_from_errno (errno);
432       log_error (_("error forking process: %s\n"), strerror (errno));
433       close (rp[0]);
434       close (rp[1]);
435       return err;
436     }
437
438   if (!*pid)
439     { /* Child. */
440       const char *arg0;
441
442       arg0 = strrchr (pgmname, '/');
443       if (arg0)
444         arg0++;
445       else
446         arg0 = pgmname;
447
448       /* Connect the infile to stdin. */
449       if (fd != 0 && dup2 (fd, 0) == -1)
450         log_fatal ("dup2 stdin failed: %s\n", strerror (errno));
451
452       /* Connect the outfile to stdout. */
453       if (fdout != 1 && dup2 (fdout, 1) == -1)
454         log_fatal ("dup2 stdout failed: %s\n", strerror (errno));
455       
456       /* Connect stderr to our pipe. */
457       if (rp[1] != 2 && dup2 (rp[1], 2) == -1)
458         log_fatal ("dup2 stderr failed: %s\n", strerror (errno));
459
460       /* Close all other files. */
461       n = sysconf (_SC_OPEN_MAX);
462       if (n < 0)
463         n = MAX_OPEN_FDS;
464       for (i=3; i < n; i++)
465         close(i);
466       errno = 0;
467
468       execlp (pgmname, arg0,
469               "--homedir", opt.homedir,
470               "--p12-export",
471               "--prompt", prompt?prompt:"", 
472               "--",
473               keygrip,
474               NULL);
475       /* No way to print anything, as we have closed all streams. */
476       _exit (31);
477     }
478
479   /* Parent. */
480   close (rp[1]);
481   *statusfile = fdopen (rp[0], "r");
482   if (!*statusfile)
483     {
484       err = gpg_error_from_errno (errno);
485       log_error ("can't fdopen pipe for reading: %s", strerror (errno));
486       kill (*pid, SIGTERM);
487       return err;
488     }
489
490   return 0;
491 }
492
493
494 static gpg_error_t
495 export_p12 (const unsigned char *certimg, size_t certimglen,
496             const char *prompt, const char *keygrip,
497             FILE **retfp)
498 {
499   const char *pgmname;
500   gpg_error_t err = 0, child_err = 0;
501   int i, c, cont_line;
502   unsigned int pos;
503   FILE *infp = NULL, *outfp = NULL, *fp = NULL;
504   char buffer[1024];
505   pid_t pid = -1;
506
507   if (!opt.protect_tool_program || !*opt.protect_tool_program)
508     pgmname = GNUPG_DEFAULT_PROTECT_TOOL;
509   else
510     pgmname = opt.protect_tool_program;
511
512   infp = tmpfile ();
513   if (!infp)
514     {
515       err = gpg_error_from_errno (errno);
516       log_error (_("error creating temporary file: %s\n"), strerror (errno));
517       goto cleanup;
518     }
519
520   if (fwrite (certimg, certimglen, 1, infp) != 1)
521     {
522       err = gpg_error_from_errno (errno);
523       log_error (_("error writing to temporary file: %s\n"),
524                  strerror (errno));
525       goto cleanup;
526     }
527
528   outfp = tmpfile ();
529   if (!outfp)
530     {
531       err = gpg_error_from_errno (errno);
532       log_error (_("error creating temporary file: %s\n"), strerror (errno));
533       goto cleanup;
534     }
535
536   err = popen_protect_tool (pgmname, infp, outfp, &fp, prompt, keygrip, &pid);
537   if (err)
538     {
539       pid = -1;
540       goto cleanup;
541     }
542   fclose (infp);
543   infp = NULL;
544
545   /* Read stderr of the protect tool. */
546   pos = 0;
547   cont_line = 0;
548   while ((c=getc (fp)) != EOF)
549     {
550       /* fixme: We could here grep for status information of the
551          protect tool to figure out better error codes for
552          CHILD_ERR. */
553       buffer[pos++] = c;
554       if (pos >= 5 /*sizeof buffer - 1*/ || c == '\n')
555         {
556           buffer[pos - (c == '\n')] = 0;
557           if (cont_line)
558             log_printf ("%s", buffer);
559           else
560             log_info ("%s", buffer);
561           pos = 0;
562           cont_line = (c != '\n');
563         }
564     }
565
566   if (pos)
567     {
568       buffer[pos] = 0;
569       if (cont_line)
570         log_printf ("%s\n", buffer);
571       else
572         log_info ("%s\n", buffer);
573     }
574   else if (cont_line)
575     log_printf ("\n");
576
577   /* If we found no error in the output of the child, setup a suitable
578      error code, which will later be reset if the exit status of the
579      child is 0. */
580   if (!child_err)
581     child_err = gpg_error (GPG_ERR_DECRYPT_FAILED);
582
583  cleanup:
584   if (infp)
585     fclose (infp);
586   if (fp)
587     fclose (fp);
588   if (pid != -1)
589     {
590       int status;
591
592       while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR)
593         ;
594       if (i == -1)
595         log_error (_("waiting for protect-tools to terminate failed: %s\n"),
596                    strerror (errno));
597       else if (WIFEXITED (status) && WEXITSTATUS (status) == 31)
598         log_error (_("error running `%s': probably not installed\n"), pgmname);
599       else if (WIFEXITED (status) && WEXITSTATUS (status))
600         log_error (_("error running `%s': exit status %d\n"), pgmname,
601                      WEXITSTATUS (status));
602       else if (!WIFEXITED (status))
603         log_error (_("error running `%s': terminated\n"), pgmname);
604       else 
605         child_err = 0;
606     }
607   if (!err)
608     err = child_err;
609   if (err)
610     {
611       if (outfp)
612         fclose (outfp);
613     }
614   else
615     *retfp = outfp;
616   return err;
617 }
618