Bump to 2.4.3
[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   if (opt.verbose)
179     log_info ("fetching CRL from '%s'\n", url);
180
181   err = http_parse_uri (&uri, url, 0);
182   http_release_parsed_uri (uri);
183   if (!err) /* Yes, our HTTP code groks that. */
184     {
185       if (opt.disable_http)
186         {
187           log_error (_("CRL access not possible due to disabled %s\n"),
188                      "HTTP");
189           err = gpg_error (GPG_ERR_NOT_SUPPORTED);
190         }
191       else
192         {
193           /* Note that we also allow root certificates loaded from
194            * "/etc/gnupg/trusted-certs/".  We also do not consult the
195            * CRL for the TLS connection - that may lead to a loop.
196            * Due to cacert.org redirecting their https URL to http we
197            * also allow such a downgrade.  */
198           err = ks_http_fetch (ctrl, url,
199                                (KS_HTTP_FETCH_TRUST_CFG
200                                 | KS_HTTP_FETCH_NO_CRL
201                                 | KS_HTTP_FETCH_ALLOW_DOWNGRADE ),
202                                &httpfp);
203         }
204
205       if (err)
206         log_error (_("error retrieving '%s': %s\n"), url, gpg_strerror (err));
207       else
208         {
209           struct reader_cb_context_s *cb_ctx;
210
211           cb_ctx = xtrycalloc (1, sizeof *cb_ctx);
212           if (!cb_ctx)
213             err = gpg_error_from_syserror ();
214           else if (!(err = ksba_reader_new (reader)))
215             {
216               cb_ctx->fp = httpfp;
217               err = ksba_reader_set_cb (*reader, &my_es_read, cb_ctx);
218               if (!err)
219                 {
220                   /* The ksba reader misses a user pointer thus we
221                    * need to come up with our own way of associating a
222                    * file pointer (or well the callback context) with
223                    * the reader.  It is only required when closing the
224                    * reader thus there is no performance issue doing
225                    * it this way.  FIXME: We now have a close
226                    * notification which might be used here. */
227                   register_file_reader (*reader, cb_ctx);
228                   httpfp = NULL;
229                 }
230             }
231
232           if (err)
233             {
234               log_error (_("error initializing reader object: %s\n"),
235                          gpg_strerror (err));
236               ksba_reader_release (*reader);
237               *reader = NULL;
238               xfree (cb_ctx);
239             }
240         }
241     }
242   else /* Let the LDAP code parse other schemes.  */
243     {
244       if (opt.disable_ldap)
245         {
246           log_error (_("CRL access not possible due to disabled %s\n"),
247                      "LDAP");
248           err = gpg_error (GPG_ERR_NOT_SUPPORTED);
249         }
250       else if (dirmngr_use_tor ())
251         {
252           err = no_crl_due_to_tor (ctrl);
253         }
254       else
255         {
256 #       if USE_LDAP
257           err = url_fetch_ldap (ctrl, url, reader);
258 #       else /*!USE_LDAP*/
259           err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
260 #       endif /*!USE_LDAP*/
261         }
262     }
263
264   es_fclose (httpfp);
265   return err;
266 }
267
268
269 /* Fetch CRL for ISSUER using a default server. Return the entire CRL
270    as a newly opened stream returned in R_FP. */
271 gpg_error_t
272 crl_fetch_default (ctrl_t ctrl, const char *issuer, ksba_reader_t *reader)
273 {
274   if (dirmngr_use_tor ())
275     {
276       return no_crl_due_to_tor (ctrl);
277     }
278   if (opt.disable_ldap)
279     {
280       log_error (_("CRL access not possible due to disabled %s\n"),
281                  "LDAP");
282       return gpg_error (GPG_ERR_NOT_SUPPORTED);
283     }
284
285 #if USE_LDAP
286   return attr_fetch_ldap (ctrl, issuer, "certificateRevocationList",
287                           reader);
288 #else
289   (void)ctrl;
290   (void)issuer;
291   (void)reader;
292   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
293 #endif
294 }
295
296
297 /* Fetch a CA certificate for DN using the default server.  This
298  * function only initiates the fetch; fetch_next_cert must be used to
299  * actually read the certificate; end_cert_fetch to end the
300  * operation.  */
301 gpg_error_t
302 ca_cert_fetch (ctrl_t ctrl, cert_fetch_context_t *context, const char *dn)
303 {
304   if (dirmngr_use_tor ())
305     {
306       return no_crl_due_to_tor (ctrl);
307     }
308   if (opt.disable_ldap)
309     {
310       log_error (_("CRL access not possible due to disabled %s\n"),
311                  "LDAP");
312       return gpg_error (GPG_ERR_NOT_SUPPORTED);
313     }
314 #if USE_LDAP
315   return start_cacert_fetch_ldap (ctrl, context, dn);
316 #else
317   (void)ctrl;
318   (void)context;
319   (void)dn;
320   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
321 #endif
322 }
323
324
325 gpg_error_t
326 start_cert_fetch (ctrl_t ctrl, cert_fetch_context_t *context,
327                   strlist_t patterns, const ldap_server_t server)
328 {
329   if (dirmngr_use_tor ())
330     {
331       return no_crl_due_to_tor (ctrl);
332     }
333   if (opt.disable_ldap)
334     {
335       log_error (_("certificate search not possible due to disabled %s\n"),
336                  "LDAP");
337       return gpg_error (GPG_ERR_NOT_SUPPORTED);
338     }
339 #if USE_LDAP
340   return start_cert_fetch_ldap (ctrl, context, patterns, server);
341 #else
342   (void)ctrl;
343   (void)context;
344   (void)patterns;
345   (void)server;
346   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
347 #endif
348 }
349
350
351 gpg_error_t
352 fetch_next_cert (cert_fetch_context_t context,
353                  unsigned char **value, size_t * valuelen)
354 {
355 #if USE_LDAP
356   return fetch_next_cert_ldap (context, value, valuelen);
357 #else
358   (void)context;
359   (void)value;
360   (void)valuelen;
361   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
362 #endif
363 }
364
365
366 /* Fetch the next data from CONTEXT, assuming it is a certificate and return
367  * it as a cert object in R_CERT.  */
368 gpg_error_t
369 fetch_next_ksba_cert (cert_fetch_context_t context, ksba_cert_t *r_cert)
370 {
371   gpg_error_t err;
372   unsigned char *value = NULL;
373   size_t valuelen = 0;
374   ksba_cert_t cert;
375
376   *r_cert = NULL;
377
378 #if USE_LDAP
379   err = fetch_next_cert_ldap (context, &value, &valuelen);
380   if (!err && !value)
381     err = gpg_error (GPG_ERR_BUG);
382 #else
383   (void)context;
384   err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
385 #endif
386   if (err)
387     return err;
388
389   err = ksba_cert_new (&cert);
390   if (err)
391     {
392       xfree (value);
393       return err;
394     }
395
396   err = ksba_cert_init_from_mem (cert, value, valuelen);
397   xfree (value);
398   if (err)
399     {
400       ksba_cert_release (cert);
401       return err;
402     }
403   *r_cert = cert;
404   return 0;
405 }
406
407
408 void
409 end_cert_fetch (cert_fetch_context_t context)
410 {
411 #if USE_LDAP
412   end_cert_fetch_ldap (context);
413 #else
414   (void)context;
415 #endif
416 }
417
418
419 /* Read a certificate from an HTTP URL and return it as an estream
420  * memory buffer at R_FP.  */
421 static gpg_error_t
422 read_cert_via_http (ctrl_t ctrl, const char *url, estream_t *r_fp)
423 {
424   gpg_error_t err;
425   estream_t fp = NULL;
426   estream_t httpfp = NULL;
427   size_t nread, nwritten;
428   char buffer[1024];
429
430   if ((err = ks_http_fetch (ctrl, url, KS_HTTP_FETCH_TRUST_CFG, &httpfp)))
431     goto leave;
432
433   /* We now read the data from the web server into a memory buffer.
434    * To DOS we limit the certificate length to 32k.  */
435   fp = es_fopenmem (32*1024, "rw");
436   if (!fp)
437     {
438       err = gpg_error_from_syserror ();
439       log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
440       goto leave;
441     }
442
443   for (;;)
444     {
445       if (es_read (httpfp, buffer, sizeof buffer, &nread))
446         {
447           err = gpg_error_from_syserror ();
448           log_error ("error reading '%s': %s\n",
449                      es_fname_get (httpfp), gpg_strerror (err));
450           goto leave;
451         }
452
453       if (!nread)
454         break; /* Ready.  */
455       if (es_write (fp, buffer, nread, &nwritten))
456         {
457           err = gpg_error_from_syserror ();
458           log_error ("error writing '%s': %s\n",
459                      es_fname_get (fp), gpg_strerror (err));
460           goto leave;
461         }
462       else if (nread != nwritten)
463         {
464           err = gpg_error (GPG_ERR_EIO);
465           log_error ("error writing '%s': %s\n",
466                      es_fname_get (fp), "short write");
467           goto leave;
468         }
469     }
470
471   es_rewind (fp);
472   *r_fp = fp;
473   fp = NULL;
474
475  leave:
476   es_fclose (httpfp);
477   es_fclose (fp);
478   return err;
479 }
480
481
482 /* Lookup a cert by it's URL.  */
483 gpg_error_t
484 fetch_cert_by_url (ctrl_t ctrl, const char *url,
485                    unsigned char **value, size_t *valuelen)
486 {
487   const unsigned char *cert_image = NULL;
488   size_t cert_image_n;
489   ksba_reader_t reader = NULL;
490   ksba_cert_t cert = NULL;
491   gpg_error_t err;
492
493   *value = NULL;
494   *valuelen = 0;
495
496   err = ksba_cert_new (&cert);
497   if (err)
498     goto leave;
499
500   if (url && (!strncmp (url, "http:", 5) || !strncmp (url, "https:", 6)))
501     {
502       estream_t stream;
503       void *der;
504       size_t derlen;
505
506       err = read_cert_via_http (ctrl, url, &stream);
507       if (err)
508         goto leave;
509
510       if (es_fclose_snatch (stream, &der, &derlen))
511         {
512           err = gpg_error_from_syserror ();
513           goto leave;
514         }
515
516       err = ksba_cert_init_from_mem (cert, der, derlen);
517       xfree (der);
518       if (err)
519         goto leave;
520     }
521   else /* Assume LDAP.  */
522     {
523 #if USE_LDAP
524       err = url_fetch_ldap (ctrl, url, &reader);
525 #else
526       (void)ctrl;
527       (void)url;
528       err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
529 #endif /*USE_LDAP*/
530       if (err)
531         goto leave;
532
533       err = ksba_cert_read_der (cert, reader);
534       if (err)
535         goto leave;
536     }
537
538   cert_image = ksba_cert_get_image (cert, &cert_image_n);
539   if (!cert_image || !cert_image_n)
540     {
541       err = gpg_error (GPG_ERR_INV_CERT_OBJ);
542       goto leave;
543     }
544
545   *value = xtrymalloc (cert_image_n);
546   if (!*value)
547     {
548       err = gpg_error_from_syserror ();
549       goto leave;
550     }
551
552   memcpy (*value, cert_image, cert_image_n);
553   *valuelen = cert_image_n;
554
555  leave:
556   ksba_cert_release (cert);
557 #if USE_LDAP
558   ldap_wrapper_release_context (reader);
559 #endif /*USE_LDAP*/
560
561   return err;
562 }
563
564 /* This function is to be used to close the reader object.  In
565    addition to running ksba_reader_release it also releases the LDAP
566    or HTTP contexts associated with that reader.  */
567 void
568 crl_close_reader (ksba_reader_t reader)
569 {
570   struct reader_cb_context_s *cb_ctx;
571
572   if (!reader)
573     return;
574
575   /* Check whether this is a HTTP one. */
576   cb_ctx = get_file_reader (reader);
577   if (cb_ctx)
578     {
579       /* This is an HTTP context. */
580       if (cb_ctx->fp)
581         es_fclose (cb_ctx->fp);
582       /* Release the base64 decoder state.  */
583       if (cb_ctx->is_pem)
584         b64dec_finish (&cb_ctx->b64state);
585       /* Release the callback context.  */
586       xfree (cb_ctx);
587     }
588   else /* This is an ldap wrapper context (Currently not used). */
589     {
590 #if USE_LDAP
591       ldap_wrapper_release_context (reader);
592 #endif /*USE_LDAP*/
593     }
594
595   /* Now get rid of the reader object. */
596   ksba_reader_release (reader);
597 }