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/>.
33 # include "ldap-wrapper.h"
36 /* For detecting armored CRLs received via HTTP (yes, such CRLS really
37 exits, e.g. http://grid.fzk.de/ca/gridka-crl.pem at least in June
38 2008) we need a context in the reader callback. */
39 struct reader_cb_context_s
41 estream_t fp; /* The stream used with the ksba reader. */
42 int checked:1; /* PEM/binary detection ahs been done. */
43 int is_pem:1; /* The file stream is PEM encoded. */
44 struct b64state b64state; /* The state used for Base64 decoding. */
48 /* We need to associate a reader object with the reader callback
49 context. This table is used for it. */
50 struct file_reader_map_s
53 struct reader_cb_context_s *cb_ctx;
55 #define MAX_FILE_READER 50
56 static struct file_reader_map_s file_reader_map[MAX_FILE_READER];
58 /* Associate FP with READER. If the table is full wait until another
59 thread has removed an entry. */
61 register_file_reader (ksba_reader_t reader, struct reader_cb_context_s *cb_ctx)
67 for (i=0; i < MAX_FILE_READER; i++)
68 if (!file_reader_map[i].reader)
70 file_reader_map[i].reader = reader;
71 file_reader_map[i].cb_ctx = cb_ctx;
74 log_info (_("reader to file mapping table full - waiting\n"));
79 /* Scan the table for an entry matching READER, remove that entry and
80 return the associated file pointer. */
81 static struct reader_cb_context_s *
82 get_file_reader (ksba_reader_t reader)
84 struct reader_cb_context_s *cb_ctx = NULL;
87 for (i=0; i < MAX_FILE_READER; i++)
88 if (file_reader_map[i].reader == reader)
90 cb_ctx = file_reader_map[i].cb_ctx;
91 file_reader_map[i].reader = NULL;
92 file_reader_map[i].cb_ctx = NULL;
101 my_es_read (void *opaque, char *buffer, size_t nbytes, size_t *nread)
103 struct reader_cb_context_s *cb_ctx = opaque;
106 result = es_read (cb_ctx->fp, buffer, nbytes, nread);
109 /* Fixme we should check whether the semantics of es_read are okay
110 and well defined. I have some doubts. */
111 if (nbytes && !*nread && es_feof (cb_ctx->fp))
112 return gpg_error (GPG_ERR_EOF);
113 if (!nread && es_ferror (cb_ctx->fp))
114 return gpg_error (GPG_ERR_EIO);
116 if (!cb_ctx->checked && *nread)
118 int c = *(unsigned char *)buffer;
121 if ( ((c & 0xc0) >> 6) == 0 /* class: universal */
122 && (c & 0x1f) == 16 /* sequence */
123 && (c & 0x20) /* is constructed */ )
128 b64dec_start (&cb_ctx->b64state, "");
131 if (cb_ctx->is_pem && *nread)
135 if (b64dec_proc (&cb_ctx->b64state, buffer, *nread, &nread2))
137 /* EOF from decoder. */
139 result = gpg_error (GPG_ERR_EOF);
149 /* Fetch CRL from URL and return the entire CRL using new ksba reader
150 object in READER. Note that this reader object should be closed
151 only using ldap_close_reader. */
153 crl_fetch (ctrl_t ctrl, const char *url, ksba_reader_t *reader)
157 char *free_this = NULL;
158 int redirects_left = 2; /* We allow for 2 redirect levels. */
163 return gpg_error (GPG_ERR_INV_ARG);
166 err = http_parse_uri (&uri, url, 0);
167 http_release_parsed_uri (uri);
168 if (err && !strncmp (url, "https:", 6))
170 /* Our HTTP code does not support TLS, thus we can't use this
171 scheme and it is frankly not useful for CRL retrieval anyway.
172 We resort to using http, assuming that the server also
173 provides plain http access. */
174 free_this = xtrymalloc (strlen (url) + 1);
177 strcpy (stpcpy (free_this,"http:"), url+6);
178 err = http_parse_uri (&uri, free_this, 0);
179 http_release_parsed_uri (uri);
182 log_info (_("using \"http\" instead of \"https\"\n"));
187 if (!err) /* Yes, our HTTP code groks that. */
191 if (opt.disable_http)
193 log_error (_("CRL access not possible due to disabled %s\n"),
195 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
198 err = http_open_document (&hd, url, NULL,
199 ((opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0)
200 |(DBG_LOOKUP? HTTP_FLAG_LOG_RESP:0)
201 |(opt.use_tor? HTTP_FLAG_FORCE_TOR:0)
202 |(opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4:0)
204 ctrl->http_proxy, NULL, NULL, NULL);
206 switch ( err? 99999 : http_get_status_code (hd) )
210 estream_t fp = http_get_read_ptr (hd);
211 struct reader_cb_context_s *cb_ctx;
213 cb_ctx = xtrycalloc (1, sizeof *cb_ctx);
215 err = gpg_error_from_syserror ();
217 err = ksba_reader_new (reader);
221 err = ksba_reader_set_cb (*reader, &my_es_read, cb_ctx);
225 log_error (_("error initializing reader object: %s\n"),
227 ksba_reader_release (*reader);
233 /* The ksba reader misses a user pointer thus we need
234 to come up with our own way of associating a file
235 pointer (or well the callback context) with the
236 reader. It is only required when closing the
237 reader thus there is no performance issue doing it
238 this way. FIXME: We now have a close notification
239 which might be used here. */
240 register_file_reader (*reader, cb_ctx);
246 case 301: /* Redirection (perm.). */
247 case 302: /* Redirection (temp.). */
249 const char *s = http_get_header (hd, "Location");
251 log_info (_("URL '%s' redirected to '%s' (%u)\n"),
252 url, s?s:"[none]", http_get_status_code (hd));
253 if (s && *s && redirects_left-- )
255 xfree (free_this); url = NULL;
256 free_this = xtrystrdup (s);
258 err = gpg_error_from_errno (errno);
263 /* Note, that our implementation of redirection
264 actually handles a redirect to LDAP. */
269 err = gpg_error (GPG_ERR_NO_DATA);
270 log_error (_("too many redirections\n")); /* Or no "Location". */
275 case 99999: /* Made up status code for error reporting. */
276 log_error (_("error retrieving '%s': %s\n"),
277 url, gpg_strerror (err));
281 log_error (_("error retrieving '%s': http status %u\n"),
282 url, http_get_status_code (hd));
283 err = gpg_error (GPG_ERR_NO_DATA);
287 else /* Let the LDAP code try other schemes. */
289 if (opt.disable_ldap)
291 log_error (_("CRL access not possible due to disabled %s\n"),
293 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
295 else if (opt.use_tor)
297 /* For now we do not support LDAP over Tor. */
298 log_error (_("CRL access not possible due to Tor mode\n"));
299 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
304 err = url_fetch_ldap (ctrl, url, NULL, 0, reader);
306 err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
307 # endif /*!USE_LDAP*/
316 /* Fetch CRL for ISSUER using a default server. Return the entire CRL
317 as a newly opened stream returned in R_FP. */
319 crl_fetch_default (ctrl_t ctrl, const char *issuer, ksba_reader_t *reader)
323 /* For now we do not support LDAP over Tor. */
324 log_error (_("CRL access not possible due to Tor mode\n"));
325 return gpg_error (GPG_ERR_NOT_SUPPORTED);
327 if (opt.disable_ldap)
329 log_error (_("CRL access not possible due to disabled %s\n"),
331 return gpg_error (GPG_ERR_NOT_SUPPORTED);
335 return attr_fetch_ldap (ctrl, issuer, "certificateRevocationList",
341 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
346 /* Fetch a CA certificate for DN using the default server. This
347 function only initiates the fetch; fetch_next_cert must be used to
348 actually read the certificate; end_cert_fetch to end the
351 ca_cert_fetch (ctrl_t ctrl, cert_fetch_context_t *context, const char *dn)
355 /* For now we do not support LDAP over Tor. */
356 log_error (_("CRL access not possible due to Tor mode\n"));
357 return gpg_error (GPG_ERR_NOT_SUPPORTED);
359 if (opt.disable_ldap)
361 log_error (_("CRL access not possible due to disabled %s\n"),
363 return gpg_error (GPG_ERR_NOT_SUPPORTED);
366 return start_default_fetch_ldap (ctrl, context, dn, "cACertificate");
371 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
377 start_cert_fetch (ctrl_t ctrl, cert_fetch_context_t *context,
378 strlist_t patterns, const ldap_server_t server)
382 /* For now we do not support LDAP over Tor. */
383 log_error (_("CRL access not possible due to Tor mode\n"));
384 return gpg_error (GPG_ERR_NOT_SUPPORTED);
386 if (opt.disable_ldap)
388 log_error (_("certificate search not possible due to disabled %s\n"),
390 return gpg_error (GPG_ERR_NOT_SUPPORTED);
393 return start_cert_fetch_ldap (ctrl, context, patterns, server);
399 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
405 fetch_next_cert (cert_fetch_context_t context,
406 unsigned char **value, size_t * valuelen)
409 return fetch_next_cert_ldap (context, value, valuelen);
414 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
419 /* Fetch the next data from CONTEXT, assuming it is a certificate and return
420 it as a cert object in R_CERT. */
422 fetch_next_ksba_cert (cert_fetch_context_t context, ksba_cert_t *r_cert)
425 unsigned char *value;
432 err = fetch_next_cert_ldap (context, &value, &valuelen);
434 err = gpg_error (GPG_ERR_BUG);
437 err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
442 err = ksba_cert_new (&cert);
449 err = ksba_cert_init_from_mem (cert, value, valuelen);
453 ksba_cert_release (cert);
462 end_cert_fetch (cert_fetch_context_t context)
465 end_cert_fetch_ldap (context);
472 /* Lookup a cert by it's URL. */
474 fetch_cert_by_url (ctrl_t ctrl, const char *url,
475 unsigned char **value, size_t *valuelen)
477 const unsigned char *cert_image;
479 ksba_reader_t reader;
490 err = url_fetch_ldap (ctrl, url, NULL, 0, &reader);
494 err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
499 err = ksba_cert_new (&cert);
503 err = ksba_cert_read_der (cert, reader);
507 cert_image = ksba_cert_get_image (cert, &cert_image_n);
508 if (!cert_image || !cert_image_n)
510 err = gpg_error (GPG_ERR_INV_CERT_OBJ);
514 *value = xtrymalloc (cert_image_n);
517 err = gpg_error_from_syserror ();
521 memcpy (*value, cert_image, cert_image_n);
522 *valuelen = cert_image_n;
526 ksba_cert_release (cert);
528 ldap_wrapper_release_context (reader);
534 /* This function is to be used to close the reader object. In
535 addition to running ksba_reader_release it also releases the LDAP
536 or HTTP contexts associated with that reader. */
538 crl_close_reader (ksba_reader_t reader)
540 struct reader_cb_context_s *cb_ctx;
545 /* Check whether this is a HTTP one. */
546 cb_ctx = get_file_reader (reader);
549 /* This is an HTTP context. */
551 es_fclose (cb_ctx->fp);
552 /* Release the base64 decoder state. */
554 b64dec_finish (&cb_ctx->b64state);
555 /* Release the callback context. */
558 else /* This is an ldap wrapper context (Currently not used). */
561 ldap_wrapper_release_context (reader);
565 /* Now get rid of the reader object. */
566 ksba_reader_release (reader);