Imported Upstream version 2.3.8
[platform/upstream/gpg2.git] / dirmngr / crlfetch.c
1 /* crlfetch.c - LDAP access
2  *      Copyright (C) 2002 Klarälvdalens Datakonsult AB
3  *      Copyright (C) 2003, 2004, 2005, 2006, 2007 g10 Code GmbH
4  *
5  * This file is part of DirMngr.
6  *
7  * DirMngr is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * DirMngr is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <https://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22
23 #include <stdio.h>
24 #include <errno.h>
25 #include <npth.h>
26
27 #include "crlfetch.h"
28 #include "dirmngr.h"
29 #include "misc.h"
30 #include "http.h"
31 #include "ks-engine.h"  /* For ks_http_fetch.  */
32
33 #if USE_LDAP
34 # include "ldap-wrapper.h"
35 #endif
36
37 /* For detecting armored CRLs received via HTTP (yes, such CRLS really
38    exits, e.g. http://grid.fzk.de/ca/gridka-crl.pem at least in June
39    2008) we need a context in the reader callback.  */
40 struct reader_cb_context_s
41 {
42   estream_t fp;             /* The stream used with the ksba reader.  */
43   int checked:1;            /* PEM/binary detection ahs been done.    */
44   int is_pem:1;             /* The file stream is PEM encoded.        */
45   struct b64state b64state; /* The state used for Base64 decoding.    */
46 };
47
48
49 /* We need to associate a reader object with the reader callback
50    context.  This table is used for it. */
51 struct file_reader_map_s
52 {
53   ksba_reader_t reader;
54   struct reader_cb_context_s *cb_ctx;
55 };
56 #define MAX_FILE_READER 50
57 static struct file_reader_map_s file_reader_map[MAX_FILE_READER];
58
59 /* Associate FP with READER.  If the table is full wait until another
60    thread has removed an entry.  */
61 static void
62 register_file_reader (ksba_reader_t reader, struct reader_cb_context_s *cb_ctx)
63 {
64   int i;
65
66   for (;;)
67     {
68       for (i=0; i < MAX_FILE_READER; i++)
69         if (!file_reader_map[i].reader)
70           {
71             file_reader_map[i].reader = reader;
72             file_reader_map[i].cb_ctx = cb_ctx;
73             return;
74           }
75       log_info (_("reader to file mapping table full - waiting\n"));
76       gnupg_sleep (2);
77     }
78 }
79
80 /* Scan the table for an entry matching READER, remove that entry and
81    return the associated file pointer. */
82 static struct reader_cb_context_s *
83 get_file_reader (ksba_reader_t reader)
84 {
85   struct reader_cb_context_s *cb_ctx = NULL;
86   int i;
87
88   for (i=0; i < MAX_FILE_READER; i++)
89     if (file_reader_map[i].reader == reader)
90       {
91         cb_ctx = file_reader_map[i].cb_ctx;
92         file_reader_map[i].reader = NULL;
93         file_reader_map[i].cb_ctx = NULL;
94         break;
95       }
96   return cb_ctx;
97 }
98
99
100
101 static int
102 my_es_read (void *opaque, char *buffer, size_t nbytes, size_t *nread)
103 {
104   struct reader_cb_context_s *cb_ctx = opaque;
105   int result;
106
107   result = es_read (cb_ctx->fp, buffer, nbytes, nread);
108   if (result)
109     return result;
110   /* Fixme we should check whether the semantics of es_read are okay
111      and well defined.  I have some doubts.  */
112   if (nbytes && !*nread && es_feof (cb_ctx->fp))
113     return gpg_error (GPG_ERR_EOF);
114   if (!nread && es_ferror (cb_ctx->fp))
115     return gpg_error (GPG_ERR_EIO);
116
117   if (!cb_ctx->checked && *nread)
118     {
119       int c = *(unsigned char *)buffer;
120
121       cb_ctx->checked = 1;
122       if ( ((c & 0xc0) >> 6) == 0 /* class: universal */
123            && (c & 0x1f) == 16    /* sequence */
124            && (c & 0x20)          /* is constructed */ )
125         ; /* Binary data.  */
126       else
127         {
128           cb_ctx->is_pem = 1;
129           b64dec_start (&cb_ctx->b64state, "");
130         }
131     }
132   if (cb_ctx->is_pem && *nread)
133     {
134       size_t nread2;
135
136       if (b64dec_proc (&cb_ctx->b64state, buffer, *nread, &nread2))
137         {
138           /* EOF from decoder. */
139           *nread = 0;
140           result = gpg_error (GPG_ERR_EOF);
141         }
142       else
143         *nread = nread2;
144     }
145
146   return result;
147 }
148
149
150 /* For now we do not support LDAP over Tor.  */
151 static gpg_error_t
152 no_crl_due_to_tor (ctrl_t ctrl)
153 {
154   gpg_error_t err = gpg_error (GPG_ERR_NOT_SUPPORTED);
155   const char *text = _("CRL access not possible due to Tor mode");
156
157   log_error ("%s", text);
158   dirmngr_status_printf (ctrl, "NOTE", "no_crl_due_to_tor %u %s", err, text);
159   return gpg_error (GPG_ERR_NOT_SUPPORTED);
160 }
161
162
163 /* Fetch CRL from URL and return the entire CRL using new ksba reader
164    object in READER.  Note that this reader object should be closed
165    only using ldap_close_reader. */
166 gpg_error_t
167 crl_fetch (ctrl_t ctrl, const char *url, ksba_reader_t *reader)
168 {
169   gpg_error_t err;
170   parsed_uri_t uri;
171   estream_t httpfp = NULL;
172
173   *reader = NULL;
174
175   if (!url)
176     return gpg_error (GPG_ERR_INV_ARG);
177
178   err = http_parse_uri (&uri, url, 0);
179   http_release_parsed_uri (uri);
180   if (!err) /* Yes, our HTTP code groks that. */
181     {
182       if (opt.disable_http)
183         {
184           log_error (_("CRL access not possible due to disabled %s\n"),
185                      "HTTP");
186           err = gpg_error (GPG_ERR_NOT_SUPPORTED);
187         }
188       else
189         {
190           /* Note that we also allow root certificates loaded from
191            * "/etc/gnupg/trusted-certs/".  We also do not consult the
192            * CRL for the TLS connection - that may lead to a loop.
193            * Due to cacert.org redirecting their https URL to http we
194            * also allow such a downgrade.  */
195           err = ks_http_fetch (ctrl, url,
196                                (KS_HTTP_FETCH_TRUST_CFG
197                                 | KS_HTTP_FETCH_NO_CRL
198                                 | KS_HTTP_FETCH_ALLOW_DOWNGRADE ),
199                                &httpfp);
200         }
201
202       if (err)
203         log_error (_("error retrieving '%s': %s\n"), url, gpg_strerror (err));
204       else
205         {
206           struct reader_cb_context_s *cb_ctx;
207
208           cb_ctx = xtrycalloc (1, sizeof *cb_ctx);
209           if (!cb_ctx)
210             err = gpg_error_from_syserror ();
211           else if (!(err = ksba_reader_new (reader)))
212             {
213               cb_ctx->fp = httpfp;
214               err = ksba_reader_set_cb (*reader, &my_es_read, cb_ctx);
215               if (!err)
216                 {
217                   /* The ksba reader misses a user pointer thus we
218                    * need to come up with our own way of associating a
219                    * file pointer (or well the callback context) with
220                    * the reader.  It is only required when closing the
221                    * reader thus there is no performance issue doing
222                    * it this way.  FIXME: We now have a close
223                    * notification which might be used here. */
224                   register_file_reader (*reader, cb_ctx);
225                   httpfp = NULL;
226                 }
227             }
228
229           if (err)
230             {
231               log_error (_("error initializing reader object: %s\n"),
232                          gpg_strerror (err));
233               ksba_reader_release (*reader);
234               *reader = NULL;
235               xfree (cb_ctx);
236             }
237         }
238     }
239   else /* Let the LDAP code parse other schemes.  */
240     {
241       if (opt.disable_ldap)
242         {
243           log_error (_("CRL access not possible due to disabled %s\n"),
244                      "LDAP");
245           err = gpg_error (GPG_ERR_NOT_SUPPORTED);
246         }
247       else if (dirmngr_use_tor ())
248         {
249           err = no_crl_due_to_tor (ctrl);
250         }
251       else
252         {
253 #       if USE_LDAP
254           err = url_fetch_ldap (ctrl, url, reader);
255 #       else /*!USE_LDAP*/
256           err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
257 #       endif /*!USE_LDAP*/
258         }
259     }
260
261   es_fclose (httpfp);
262   return err;
263 }
264
265
266 /* Fetch CRL for ISSUER using a default server. Return the entire CRL
267    as a newly opened stream returned in R_FP. */
268 gpg_error_t
269 crl_fetch_default (ctrl_t ctrl, const char *issuer, ksba_reader_t *reader)
270 {
271   if (dirmngr_use_tor ())
272     {
273       return no_crl_due_to_tor (ctrl);
274     }
275   if (opt.disable_ldap)
276     {
277       log_error (_("CRL access not possible due to disabled %s\n"),
278                  "LDAP");
279       return gpg_error (GPG_ERR_NOT_SUPPORTED);
280     }
281
282 #if USE_LDAP
283   return attr_fetch_ldap (ctrl, issuer, "certificateRevocationList",
284                           reader);
285 #else
286   (void)ctrl;
287   (void)issuer;
288   (void)reader;
289   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
290 #endif
291 }
292
293
294 /* Fetch a CA certificate for DN using the default server.  This
295  * function only initiates the fetch; fetch_next_cert must be used to
296  * actually read the certificate; end_cert_fetch to end the
297  * operation.  */
298 gpg_error_t
299 ca_cert_fetch (ctrl_t ctrl, cert_fetch_context_t *context, const char *dn)
300 {
301   if (dirmngr_use_tor ())
302     {
303       return no_crl_due_to_tor (ctrl);
304     }
305   if (opt.disable_ldap)
306     {
307       log_error (_("CRL access not possible due to disabled %s\n"),
308                  "LDAP");
309       return gpg_error (GPG_ERR_NOT_SUPPORTED);
310     }
311 #if USE_LDAP
312   return start_cacert_fetch_ldap (ctrl, context, dn);
313 #else
314   (void)ctrl;
315   (void)context;
316   (void)dn;
317   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
318 #endif
319 }
320
321
322 gpg_error_t
323 start_cert_fetch (ctrl_t ctrl, cert_fetch_context_t *context,
324                   strlist_t patterns, const ldap_server_t server)
325 {
326   if (dirmngr_use_tor ())
327     {
328       return no_crl_due_to_tor (ctrl);
329     }
330   if (opt.disable_ldap)
331     {
332       log_error (_("certificate search not possible due to disabled %s\n"),
333                  "LDAP");
334       return gpg_error (GPG_ERR_NOT_SUPPORTED);
335     }
336 #if USE_LDAP
337   return start_cert_fetch_ldap (ctrl, context, patterns, server);
338 #else
339   (void)ctrl;
340   (void)context;
341   (void)patterns;
342   (void)server;
343   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
344 #endif
345 }
346
347
348 gpg_error_t
349 fetch_next_cert (cert_fetch_context_t context,
350                  unsigned char **value, size_t * valuelen)
351 {
352 #if USE_LDAP
353   return fetch_next_cert_ldap (context, value, valuelen);
354 #else
355   (void)context;
356   (void)value;
357   (void)valuelen;
358   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
359 #endif
360 }
361
362
363 /* Fetch the next data from CONTEXT, assuming it is a certificate and return
364  * it as a cert object in R_CERT.  */
365 gpg_error_t
366 fetch_next_ksba_cert (cert_fetch_context_t context, ksba_cert_t *r_cert)
367 {
368   gpg_error_t err;
369   unsigned char *value = NULL;
370   size_t valuelen = 0;
371   ksba_cert_t cert;
372
373   *r_cert = NULL;
374
375 #if USE_LDAP
376   err = fetch_next_cert_ldap (context, &value, &valuelen);
377   if (!err && !value)
378     err = gpg_error (GPG_ERR_BUG);
379 #else
380   (void)context;
381   err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
382 #endif
383   if (err)
384     return err;
385
386   err = ksba_cert_new (&cert);
387   if (err)
388     {
389       xfree (value);
390       return err;
391     }
392
393   err = ksba_cert_init_from_mem (cert, value, valuelen);
394   xfree (value);
395   if (err)
396     {
397       ksba_cert_release (cert);
398       return err;
399     }
400   *r_cert = cert;
401   return 0;
402 }
403
404
405 void
406 end_cert_fetch (cert_fetch_context_t context)
407 {
408 #if USE_LDAP
409   end_cert_fetch_ldap (context);
410 #else
411   (void)context;
412 #endif
413 }
414
415
416 /* Read a certificate from an HTTP URL and return it as an estream
417  * memory buffer at R_FP.  */
418 static gpg_error_t
419 read_cert_via_http (ctrl_t ctrl, const char *url, estream_t *r_fp)
420 {
421   gpg_error_t err;
422   estream_t fp = NULL;
423   estream_t httpfp = NULL;
424   size_t nread, nwritten;
425   char buffer[1024];
426
427   if ((err = ks_http_fetch (ctrl, url, KS_HTTP_FETCH_TRUST_CFG, &httpfp)))
428     goto leave;
429
430   /* We now read the data from the web server into a memory buffer.
431    * To DOS we limit the certificate length to 32k.  */
432   fp = es_fopenmem (32*1024, "rw");
433   if (!fp)
434     {
435       err = gpg_error_from_syserror ();
436       log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
437       goto leave;
438     }
439
440   for (;;)
441     {
442       if (es_read (httpfp, buffer, sizeof buffer, &nread))
443         {
444           err = gpg_error_from_syserror ();
445           log_error ("error reading '%s': %s\n",
446                      es_fname_get (httpfp), gpg_strerror (err));
447           goto leave;
448         }
449
450       if (!nread)
451         break; /* Ready.  */
452       if (es_write (fp, buffer, nread, &nwritten))
453         {
454           err = gpg_error_from_syserror ();
455           log_error ("error writing '%s': %s\n",
456                      es_fname_get (fp), gpg_strerror (err));
457           goto leave;
458         }
459       else if (nread != nwritten)
460         {
461           err = gpg_error (GPG_ERR_EIO);
462           log_error ("error writing '%s': %s\n",
463                      es_fname_get (fp), "short write");
464           goto leave;
465         }
466     }
467
468   es_rewind (fp);
469   *r_fp = fp;
470   fp = NULL;
471
472  leave:
473   es_fclose (httpfp);
474   es_fclose (fp);
475   return err;
476 }
477
478
479 /* Lookup a cert by it's URL.  */
480 gpg_error_t
481 fetch_cert_by_url (ctrl_t ctrl, const char *url,
482                    unsigned char **value, size_t *valuelen)
483 {
484   const unsigned char *cert_image = NULL;
485   size_t cert_image_n;
486   ksba_reader_t reader = NULL;
487   ksba_cert_t cert = NULL;
488   gpg_error_t err;
489
490   *value = NULL;
491   *valuelen = 0;
492
493   err = ksba_cert_new (&cert);
494   if (err)
495     goto leave;
496
497   if (url && (!strncmp (url, "http:", 5) || !strncmp (url, "https:", 6)))
498     {
499       estream_t stream;
500       void *der;
501       size_t derlen;
502
503       err = read_cert_via_http (ctrl, url, &stream);
504       if (err)
505         goto leave;
506
507       if (es_fclose_snatch (stream, &der, &derlen))
508         {
509           err = gpg_error_from_syserror ();
510           goto leave;
511         }
512
513       err = ksba_cert_init_from_mem (cert, der, derlen);
514       xfree (der);
515       if (err)
516         goto leave;
517     }
518   else /* Assume LDAP.  */
519     {
520 #if USE_LDAP
521       err = url_fetch_ldap (ctrl, url, &reader);
522 #else
523       (void)ctrl;
524       (void)url;
525       err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
526 #endif /*USE_LDAP*/
527       if (err)
528         goto leave;
529
530       err = ksba_cert_read_der (cert, reader);
531       if (err)
532         goto leave;
533     }
534
535   cert_image = ksba_cert_get_image (cert, &cert_image_n);
536   if (!cert_image || !cert_image_n)
537     {
538       err = gpg_error (GPG_ERR_INV_CERT_OBJ);
539       goto leave;
540     }
541
542   *value = xtrymalloc (cert_image_n);
543   if (!*value)
544     {
545       err = gpg_error_from_syserror ();
546       goto leave;
547     }
548
549   memcpy (*value, cert_image, cert_image_n);
550   *valuelen = cert_image_n;
551
552  leave:
553   ksba_cert_release (cert);
554 #if USE_LDAP
555   ldap_wrapper_release_context (reader);
556 #endif /*USE_LDAP*/
557
558   return err;
559 }
560
561 /* This function is to be used to close the reader object.  In
562    addition to running ksba_reader_release it also releases the LDAP
563    or HTTP contexts associated with that reader.  */
564 void
565 crl_close_reader (ksba_reader_t reader)
566 {
567   struct reader_cb_context_s *cb_ctx;
568
569   if (!reader)
570     return;
571
572   /* Check whether this is a HTTP one. */
573   cb_ctx = get_file_reader (reader);
574   if (cb_ctx)
575     {
576       /* This is an HTTP context. */
577       if (cb_ctx->fp)
578         es_fclose (cb_ctx->fp);
579       /* Release the base64 decoder state.  */
580       if (cb_ctx->is_pem)
581         b64dec_finish (&cb_ctx->b64state);
582       /* Release the callback context.  */
583       xfree (cb_ctx);
584     }
585   else /* This is an ldap wrapper context (Currently not used). */
586     {
587 #if USE_LDAP
588       ldap_wrapper_release_context (reader);
589 #endif /*USE_LDAP*/
590     }
591
592   /* Now get rid of the reader object. */
593   ksba_reader_release (reader);
594 }