1 /* crlfetch.c - LDAP access
2 * Copyright (C) 2002 Klarälvdalens Datakonsult AB
3 * Copyright (C) 2003, 2004, 2005, 2006, 2007 g10 Code GmbH
5 * This file is part of DirMngr.
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.
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.
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/>.
31 #include "ks-engine.h" /* For ks_http_fetch. */
34 # include "ldap-wrapper.h"
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
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. */
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
54 struct reader_cb_context_s *cb_ctx;
56 #define MAX_FILE_READER 50
57 static struct file_reader_map_s file_reader_map[MAX_FILE_READER];
59 /* Associate FP with READER. If the table is full wait until another
60 thread has removed an entry. */
62 register_file_reader (ksba_reader_t reader, struct reader_cb_context_s *cb_ctx)
68 for (i=0; i < MAX_FILE_READER; i++)
69 if (!file_reader_map[i].reader)
71 file_reader_map[i].reader = reader;
72 file_reader_map[i].cb_ctx = cb_ctx;
75 log_info (_("reader to file mapping table full - waiting\n"));
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)
85 struct reader_cb_context_s *cb_ctx = NULL;
88 for (i=0; i < MAX_FILE_READER; i++)
89 if (file_reader_map[i].reader == reader)
91 cb_ctx = file_reader_map[i].cb_ctx;
92 file_reader_map[i].reader = NULL;
93 file_reader_map[i].cb_ctx = NULL;
102 my_es_read (void *opaque, char *buffer, size_t nbytes, size_t *nread)
104 struct reader_cb_context_s *cb_ctx = opaque;
107 result = es_read (cb_ctx->fp, buffer, nbytes, nread);
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);
117 if (!cb_ctx->checked && *nread)
119 int c = *(unsigned char *)buffer;
122 if ( ((c & 0xc0) >> 6) == 0 /* class: universal */
123 && (c & 0x1f) == 16 /* sequence */
124 && (c & 0x20) /* is constructed */ )
129 b64dec_start (&cb_ctx->b64state, "");
132 if (cb_ctx->is_pem && *nread)
136 if (b64dec_proc (&cb_ctx->b64state, buffer, *nread, &nread2))
138 /* EOF from decoder. */
140 result = gpg_error (GPG_ERR_EOF);
150 /* For now we do not support LDAP over Tor. */
152 no_crl_due_to_tor (ctrl_t ctrl)
154 gpg_error_t err = gpg_error (GPG_ERR_NOT_SUPPORTED);
155 const char *text = _("CRL access not possible due to Tor mode");
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);
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. */
167 crl_fetch (ctrl_t ctrl, const char *url, ksba_reader_t *reader)
171 estream_t httpfp = NULL;
176 return gpg_error (GPG_ERR_INV_ARG);
179 log_info ("fetching CRL from '%s'\n", url);
181 err = http_parse_uri (&uri, url, 0);
182 http_release_parsed_uri (uri);
183 if (!err) /* Yes, our HTTP code groks that. */
185 if (opt.disable_http)
187 log_error (_("CRL access not possible due to disabled %s\n"),
189 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
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 ),
206 log_error (_("error retrieving '%s': %s\n"), url, gpg_strerror (err));
209 struct reader_cb_context_s *cb_ctx;
211 cb_ctx = xtrycalloc (1, sizeof *cb_ctx);
213 err = gpg_error_from_syserror ();
214 else if (!(err = ksba_reader_new (reader)))
217 err = ksba_reader_set_cb (*reader, &my_es_read, cb_ctx);
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);
234 log_error (_("error initializing reader object: %s\n"),
236 ksba_reader_release (*reader);
242 else /* Let the LDAP code parse other schemes. */
244 if (opt.disable_ldap)
246 log_error (_("CRL access not possible due to disabled %s\n"),
248 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
250 else if (dirmngr_use_tor ())
252 err = no_crl_due_to_tor (ctrl);
257 err = url_fetch_ldap (ctrl, url, reader);
259 err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
260 # endif /*!USE_LDAP*/
269 /* Fetch CRL for ISSUER using a default server. Return the entire CRL
270 as a newly opened stream returned in R_FP. */
272 crl_fetch_default (ctrl_t ctrl, const char *issuer, ksba_reader_t *reader)
274 if (dirmngr_use_tor ())
276 return no_crl_due_to_tor (ctrl);
278 if (opt.disable_ldap)
280 log_error (_("CRL access not possible due to disabled %s\n"),
282 return gpg_error (GPG_ERR_NOT_SUPPORTED);
286 return attr_fetch_ldap (ctrl, issuer, "certificateRevocationList",
292 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
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
302 ca_cert_fetch (ctrl_t ctrl, cert_fetch_context_t *context, const char *dn)
304 if (dirmngr_use_tor ())
306 return no_crl_due_to_tor (ctrl);
308 if (opt.disable_ldap)
310 log_error (_("CRL access not possible due to disabled %s\n"),
312 return gpg_error (GPG_ERR_NOT_SUPPORTED);
315 return start_cacert_fetch_ldap (ctrl, context, dn);
320 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
326 start_cert_fetch (ctrl_t ctrl, cert_fetch_context_t *context,
327 strlist_t patterns, const ldap_server_t server)
329 if (dirmngr_use_tor ())
331 return no_crl_due_to_tor (ctrl);
333 if (opt.disable_ldap)
335 log_error (_("certificate search not possible due to disabled %s\n"),
337 return gpg_error (GPG_ERR_NOT_SUPPORTED);
340 return start_cert_fetch_ldap (ctrl, context, patterns, server);
346 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
352 fetch_next_cert (cert_fetch_context_t context,
353 unsigned char **value, size_t * valuelen)
356 return fetch_next_cert_ldap (context, value, valuelen);
361 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
366 /* Fetch the next data from CONTEXT, assuming it is a certificate and return
367 * it as a cert object in R_CERT. */
369 fetch_next_ksba_cert (cert_fetch_context_t context, ksba_cert_t *r_cert)
372 unsigned char *value = NULL;
379 err = fetch_next_cert_ldap (context, &value, &valuelen);
381 err = gpg_error (GPG_ERR_BUG);
384 err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
389 err = ksba_cert_new (&cert);
396 err = ksba_cert_init_from_mem (cert, value, valuelen);
400 ksba_cert_release (cert);
409 end_cert_fetch (cert_fetch_context_t context)
412 end_cert_fetch_ldap (context);
419 /* Read a certificate from an HTTP URL and return it as an estream
420 * memory buffer at R_FP. */
422 read_cert_via_http (ctrl_t ctrl, const char *url, estream_t *r_fp)
426 estream_t httpfp = NULL;
427 size_t nread, nwritten;
430 if ((err = ks_http_fetch (ctrl, url, KS_HTTP_FETCH_TRUST_CFG, &httpfp)))
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");
438 err = gpg_error_from_syserror ();
439 log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
445 if (es_read (httpfp, buffer, sizeof buffer, &nread))
447 err = gpg_error_from_syserror ();
448 log_error ("error reading '%s': %s\n",
449 es_fname_get (httpfp), gpg_strerror (err));
455 if (es_write (fp, buffer, nread, &nwritten))
457 err = gpg_error_from_syserror ();
458 log_error ("error writing '%s': %s\n",
459 es_fname_get (fp), gpg_strerror (err));
462 else if (nread != nwritten)
464 err = gpg_error (GPG_ERR_EIO);
465 log_error ("error writing '%s': %s\n",
466 es_fname_get (fp), "short write");
482 /* Lookup a cert by it's URL. */
484 fetch_cert_by_url (ctrl_t ctrl, const char *url,
485 unsigned char **value, size_t *valuelen)
487 const unsigned char *cert_image = NULL;
489 ksba_reader_t reader = NULL;
490 ksba_cert_t cert = NULL;
496 err = ksba_cert_new (&cert);
500 if (url && (!strncmp (url, "http:", 5) || !strncmp (url, "https:", 6)))
506 err = read_cert_via_http (ctrl, url, &stream);
510 if (es_fclose_snatch (stream, &der, &derlen))
512 err = gpg_error_from_syserror ();
516 err = ksba_cert_init_from_mem (cert, der, derlen);
521 else /* Assume LDAP. */
524 err = url_fetch_ldap (ctrl, url, &reader);
528 err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
533 err = ksba_cert_read_der (cert, reader);
538 cert_image = ksba_cert_get_image (cert, &cert_image_n);
539 if (!cert_image || !cert_image_n)
541 err = gpg_error (GPG_ERR_INV_CERT_OBJ);
545 *value = xtrymalloc (cert_image_n);
548 err = gpg_error_from_syserror ();
552 memcpy (*value, cert_image, cert_image_n);
553 *valuelen = cert_image_n;
556 ksba_cert_release (cert);
558 ldap_wrapper_release_context (reader);
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. */
568 crl_close_reader (ksba_reader_t reader)
570 struct reader_cb_context_s *cb_ctx;
575 /* Check whether this is a HTTP one. */
576 cb_ctx = get_file_reader (reader);
579 /* This is an HTTP context. */
581 es_fclose (cb_ctx->fp);
582 /* Release the base64 decoder state. */
584 b64dec_finish (&cb_ctx->b64state);
585 /* Release the callback context. */
588 else /* This is an ldap wrapper context (Currently not used). */
591 ldap_wrapper_release_context (reader);
595 /* Now get rid of the reader object. */
596 ksba_reader_release (reader);