* verify.c (strtimestamp_r, gpgsm_verify):
[gnupg.git] / sm / import.c
1 /* import.c - Import certificates
2  *      Copyright (C) 2001, 2003 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
30 #include "gpgsm.h"
31 #include <gcrypt.h>
32 #include <ksba.h>
33
34 #include "keydb.h"
35 #include "i18n.h"
36
37 struct stats_s {
38   unsigned long count;
39   unsigned long imported;
40   unsigned long unchanged;
41   unsigned long not_imported;
42 };
43
44
45
46 static void
47 print_imported_status (CTRL ctrl, KsbaCert cert)
48 {
49   char *fpr;
50  
51   fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
52   gpgsm_status2 (ctrl, STATUS_IMPORTED, fpr, "[X.509]", NULL);
53   xfree (fpr);
54 }
55
56
57 /* Print an IMPORT_PROBLEM status.  REASON is one of:
58    0 := "No specific reason given".
59    1 := "Invalid Certificate".
60    2 := "Issuer Certificate missing".
61    3 := "Certificate Chain too long".
62    4 := "Error storing certificate".
63 */
64 static void
65 print_import_problem (CTRL ctrl, KsbaCert cert, int reason)
66 {
67   char *fpr = NULL;
68   char buf[25];
69   int i;
70
71   sprintf (buf, "%d", reason);
72   if (cert)
73     {
74       fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
75       /* detetect an error (all high) value */
76       for (i=0; fpr[i] == 'F'; i++)
77         ;
78       if (!fpr[i])
79         {
80           xfree (fpr);
81           fpr = NULL;
82         }
83     }
84   gpgsm_status2 (ctrl, STATUS_IMPORT_PROBLEM, buf, fpr, NULL);
85   xfree (fpr);
86 }
87
88
89 void
90 print_imported_summary (CTRL ctrl, struct stats_s *stats)
91 {
92   char buf[14*25];
93
94   if (!opt.quiet)
95     {
96       log_info (_("total number processed: %lu\n"), stats->count);
97       if (stats->imported) 
98         {
99           log_info (_("              imported: %lu"), stats->imported );
100           log_printf ("\n");
101         }
102       if (stats->unchanged)
103         log_info (_("             unchanged: %lu\n"), stats->unchanged);
104       if (stats->not_imported)
105         log_info (_("          not imported: %lu\n"), stats->not_imported);
106     }
107
108   sprintf (buf, "%lu 0 %lu 0 %lu 0 0 0 0 0 0 0 0 %lu",
109            stats->count,
110            stats->imported,
111            stats->unchanged,
112            stats->not_imported
113            );
114   gpgsm_status (ctrl, STATUS_IMPORT_RES, buf);
115 }
116
117
118
119 static void
120 check_and_store (CTRL ctrl, struct stats_s *stats, KsbaCert cert, int depth)
121 {
122   int rc;
123
124   stats->count++;
125   if ( depth >= 50 )
126     {
127       log_error (_("certificate chain too long\n"));
128       stats->not_imported++;
129       print_import_problem (ctrl, cert, 3);
130       return;
131     }
132
133   rc = gpgsm_basic_cert_check (cert);
134   if (!rc)
135     {
136       int existed;
137
138       if (!keydb_store_cert (cert, 0, &existed))
139         {
140           KsbaCert next = NULL;
141
142           if (!existed)
143             {
144               print_imported_status (ctrl, cert);
145               stats->imported++;
146             }
147           else
148             stats->unchanged++;
149             
150           if (opt.verbose > 1 && existed)
151             {
152               if (depth)
153                 log_info ("issuer certificate already in DB\n");
154               else
155                 log_info ("certificate already in DB\n");
156             }
157           else if (opt.verbose && !existed)
158             {
159               if (depth)
160                 log_info ("issuer certificate imported\n");
161               else
162                 log_info ("certificate imported\n");
163             }
164           /* Now lets walk up the chain and import all certificates up
165              the chain.*/
166           else if (!gpgsm_walk_cert_chain (cert, &next))
167             {
168               check_and_store (ctrl, stats, next, depth+1);
169               ksba_cert_release (next);
170             }
171         }
172       else
173         {
174           log_error (_("error storing certificate\n"));
175           stats->not_imported++;
176           print_import_problem (ctrl, cert, 4);
177         }
178     }
179   else
180     {
181       log_error (_("basic certificate checks failed - not imported\n"));
182       stats->not_imported++;
183       print_import_problem (ctrl, cert,
184                             gpg_err_code (rc) == GPG_ERR_MISSING_CERT? 2 :
185                             gpg_err_code (rc) == GPG_ERR_BAD_CERT?     1 : 0);
186     }
187 }
188
189
190 \f
191
192 static int
193 import_one (CTRL ctrl, struct stats_s *stats, int in_fd)
194 {
195   int rc;
196   Base64Context b64reader = NULL;
197   KsbaReader reader;
198   KsbaCert cert = NULL;
199   KsbaCMS cms = NULL;
200   FILE *fp = NULL;
201   KsbaContentType ct;
202
203   fp = fdopen ( dup (in_fd), "rb");
204   if (!fp)
205     {
206       rc = gpg_error (gpg_err_code_from_errno (errno));
207       log_error ("fdopen() failed: %s\n", strerror (errno));
208       goto leave;
209     }
210
211   rc = gpgsm_create_reader (&b64reader, ctrl, fp, &reader);
212   if (rc)
213     {
214       log_error ("can't create reader: %s\n", gpg_strerror (rc));
215       goto leave;
216     }
217
218   ct = ksba_cms_identify (reader);
219   if (ct == KSBA_CT_SIGNED_DATA)
220     { /* This is probably a signed-only message - import the certs */
221       KsbaStopReason stopreason;
222       int i;
223
224       cms = ksba_cms_new ();
225       if (!cms)
226         {
227           rc = gpg_error (GPG_ERR_ENOMEM);
228           goto leave;
229         }
230
231       rc = ksba_cms_set_reader_writer (cms, reader, NULL);
232       if (rc)
233         {
234           log_error ("ksba_cms_set_reader_writer failed: %s\n",
235                      ksba_strerror (rc));
236           rc = map_ksba_err (rc);
237           goto leave;
238         }
239
240
241       do 
242         {
243           rc = ksba_cms_parse (cms, &stopreason);
244           if (rc)
245             {
246               log_error ("ksba_cms_parse failed: %s\n", ksba_strerror (rc));
247               rc = map_ksba_err (rc);
248               goto leave;
249             }
250
251           if (stopreason == KSBA_SR_BEGIN_DATA)
252               log_info ("not a certs-only message\n");
253         }
254       while (stopreason != KSBA_SR_READY);   
255       
256       for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++)
257         {
258           check_and_store (ctrl, stats, cert, 0);
259           ksba_cert_release (cert); 
260           cert = NULL;
261         }
262       if (!i)
263         log_error ("no certificate found\n");
264     }
265   else if (ct == KSBA_CT_NONE)
266     { /* Failed to identify this message - assume a certificate */
267
268       cert = ksba_cert_new ();
269       if (!cert)
270         {
271           rc = gpg_error (GPG_ERR_ENOMEM);
272           goto leave;
273         }
274
275       rc = ksba_cert_read_der (cert, reader);
276       if (rc)
277         {
278           rc = map_ksba_err (rc);
279           goto leave;
280         }
281
282       check_and_store (ctrl, stats, cert, 0);
283     }
284   else
285     {
286       log_error ("can't extract certificates from input\n");
287       rc = gpg_error (GPG_ERR_NO_DATA);
288     }
289    
290  leave:
291   ksba_cms_release (cms);
292   ksba_cert_release (cert);
293   gpgsm_destroy_reader (b64reader);
294   if (fp)
295     fclose (fp);
296   return rc;
297 }
298
299
300 int
301 gpgsm_import (CTRL ctrl, int in_fd)
302 {
303   int rc;
304   struct stats_s stats;
305
306   memset (&stats, 0, sizeof stats);
307   rc = import_one (ctrl, &stats, in_fd);
308   print_imported_summary (ctrl, &stats);
309   /* If we never printed an error message do it now so that a command
310      line invocation will return with an error (log_error keeps a
311      global errorcount) */
312   if (rc && !log_get_errorcount (0))
313     log_error (_("error importing certificate: %s\n"), gpg_strerror (rc));
314   return rc;
315 }
316
317
318 int
319 gpgsm_import_files (CTRL ctrl, int nfiles, char **files,
320                     int (*of)(const char *fname))
321 {
322   int rc = 0;
323   struct stats_s stats;
324
325   memset (&stats, 0, sizeof stats);
326   
327   if (!nfiles)
328     rc = import_one (ctrl, &stats, 0);
329   else
330     {
331       for (; nfiles && !rc ; nfiles--, files++)
332         {
333           int fd = of (*files);
334           rc = import_one (ctrl, &stats, fd);
335           close (fd);
336           if (rc == -1)
337             rc = 0;
338         }
339     }
340   print_imported_summary (ctrl, &stats);
341   /* If we never printed an error message do it now so that a command
342      line invocation will return with an error (log_error keeps a
343      global errorcount) */
344   if (rc && !log_get_errorcount (0))
345     log_error (_("error importing certificate: %s\n"), gpg_strerror (rc));
346   return rc;
347 }
348
349