1 /*
2 * Copyright 2016 Fiona Klute
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "gnutls_ocsp.h"
18 #include "mod_gnutls.h"
19 #include "gnutls_cache.h"
20 #include "gnutls_config.h"
21 #include "gnutls_util.h"
22
23 #include <apr_escape.h>
24 #include <apr_lib.h>
25 #include <apr_time.h>
26 #include <gnutls/ocsp.h>
27 #include <time.h>
28
29 #ifdef APLOG_USE_MODULE
30 APLOG_USE_MODULE(gnutls);
31 #endif
32
33 /** maximum supported OCSP response size, 8K should be plenty */
34 #define OCSP_RESP_SIZE_MAX (8 * 1024)
35 #define OCSP_REQ_TYPE "application/ocsp-request"
36 #define OCSP_RESP_TYPE "application/ocsp-response"
37
38 /** Dummy data for failure cache entries (one byte). */
39 #define OCSP_FAILURE_CACHE_DATA 0x0f
40
41
42 #define _log_one_ocsp_fail(str, srv) \
43 ap_log_error(APLOG_MARK, APLOG_INFO, APR_EGENERAL, (srv), \
44 "Reason for failed OCSP response verification: %s", (str))
45 /**
46 * Log all matching reasons for verification failure
47 */
_log_verify_fail_reason(const unsigned int verify,server_rec * s)48 static void _log_verify_fail_reason(const unsigned int verify, server_rec *s)
49 {
50 if (verify & GNUTLS_OCSP_VERIFY_SIGNER_NOT_FOUND)
51 _log_one_ocsp_fail("Signer cert not found", s);
52
53 if (verify & GNUTLS_OCSP_VERIFY_SIGNER_KEYUSAGE_ERROR)
54 _log_one_ocsp_fail("Signer cert keyusage error", s);
55
56 if (verify & GNUTLS_OCSP_VERIFY_UNTRUSTED_SIGNER)
57 _log_one_ocsp_fail("Signer cert is not trusted", s);
58
59 if (verify & GNUTLS_OCSP_VERIFY_INSECURE_ALGORITHM)
60 _log_one_ocsp_fail("Insecure algorithm", s);
61
62 if (verify & GNUTLS_OCSP_VERIFY_SIGNATURE_FAILURE)
63 _log_one_ocsp_fail("Signature failure", s);
64
65 if (verify & GNUTLS_OCSP_VERIFY_CERT_NOT_ACTIVATED)
66 _log_one_ocsp_fail("Signer cert not yet activated", s);
67
68 if (verify & GNUTLS_OCSP_VERIFY_CERT_EXPIRED)
69 _log_one_ocsp_fail("Signer cert expired", s);
70 }
71
72
73
mgs_ocsp_stapling_enable(cmd_parms * parms,void * dummy,const int arg)74 const char *mgs_ocsp_stapling_enable(cmd_parms *parms,
75 void *dummy __attribute__((unused)),
76 const int arg)
77 {
78 mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
79 ap_get_module_config(parms->server->module_config, &gnutls_module);
80
81 if (arg)
82 sc->ocsp_staple = GNUTLS_ENABLED_TRUE;
83 else
84 sc->ocsp_staple = GNUTLS_ENABLED_FALSE;
85
86 return NULL;
87 }
88
89
90
mgs_set_ocsp_check_nonce(cmd_parms * parms,void * dummy,const int arg)91 const char *mgs_set_ocsp_check_nonce(cmd_parms *parms,
92 void *dummy __attribute__((unused)),
93 const int arg)
94 {
95 mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
96 ap_get_module_config(parms->server->module_config, &gnutls_module);
97
98 if (arg)
99 sc->ocsp_check_nonce = GNUTLS_ENABLED_TRUE;
100 else
101 sc->ocsp_check_nonce = GNUTLS_ENABLED_FALSE;
102
103 return NULL;
104 }
105
106
107
mgs_store_ocsp_response_path(cmd_parms * parms,void * dummy,const char * arg)108 const char *mgs_store_ocsp_response_path(cmd_parms *parms,
109 void *dummy __attribute__((unused)),
110 const char *arg)
111 {
112 mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
113 ap_get_module_config(parms->server->module_config, &gnutls_module);
114
115 sc->ocsp_response_file = ap_server_root_relative(parms->pool, arg);
116 return NULL;
117 }
118
119
120
121 /**
122 * Create an OCSP request for the certificate of the given server. The
123 * DER encoded request is stored in 'req' (must be released with
124 * gnutls_free() when no longer needed), its nonce in 'nonce' (same,
125 * if not NULL).
126 *
127 * Returns GNUTLS_E_SUCCESS, or a GnuTLS error code.
128 */
129 static int mgs_create_ocsp_request(server_rec *s, gnutls_datum_t *req,
130 gnutls_datum_t *nonce)
131 __attribute__((nonnull(1, 2)));
mgs_create_ocsp_request(server_rec * s,gnutls_datum_t * req,gnutls_datum_t * nonce)132 static int mgs_create_ocsp_request(server_rec *s, gnutls_datum_t *req,
133 gnutls_datum_t *nonce)
134 {
135 mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
136 ap_get_module_config(s->module_config, &gnutls_module);
137
138 gnutls_ocsp_req_t r;
139 int ret = gnutls_ocsp_req_init(&r);
140 if (ret != GNUTLS_E_SUCCESS)
141 {
142 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
143 "Could not initialize OCSP request structure: %s (%d)",
144 gnutls_strerror(ret), ret);
145 return ret;
146 }
147
148 /* GnuTLS doc says that the digest is "normally"
149 * GNUTLS_DIG_SHA1. */
150 ret = gnutls_ocsp_req_add_cert(r, GNUTLS_DIG_SHA256,
151 sc->certs_x509_crt_chain[1],
152 sc->certs_x509_crt_chain[0]);
153
154 if (ret != GNUTLS_E_SUCCESS)
155 {
156 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
157 "Adding certificate to OCSP request for %s:%d "
158 "failed: %s (%d)",
159 s->server_hostname, s->addrs->host_port,
160 gnutls_strerror(ret), ret);
161 gnutls_ocsp_req_deinit(r);
162 return ret;
163 }
164
165 ret = gnutls_ocsp_req_randomize_nonce(r);
166 if (ret != GNUTLS_E_SUCCESS)
167 {
168 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
169 "OCSP nonce creation failed: %s (%d)",
170 gnutls_strerror(ret), ret);
171 gnutls_ocsp_req_deinit(r);
172 return ret;
173 }
174
175 if (nonce != NULL)
176 {
177 ret = gnutls_ocsp_req_get_nonce(r, NULL, nonce);
178 if (ret != GNUTLS_E_SUCCESS)
179 {
180 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
181 "Could not get nonce: %s (%d)",
182 gnutls_strerror(ret), ret);
183 gnutls_free(nonce->data);
184 nonce->data = NULL;
185 nonce->size = 0;
186 gnutls_ocsp_req_deinit(r);
187 return ret;
188 }
189 }
190
191 ret = gnutls_ocsp_req_export(r, req);
192 if (ret != GNUTLS_E_SUCCESS)
193 {
194 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
195 "OCSP request export failed: %s (%d)",
196 gnutls_strerror(ret), ret);
197 gnutls_free(req->data);
198 req->data = NULL;
199 req->size = 0;
200 if (nonce != NULL)
201 {
202 gnutls_free(nonce->data);
203 nonce->data = NULL;
204 nonce->size = 0;
205 }
206 gnutls_ocsp_req_deinit(r);
207 return ret;
208 }
209
210 gnutls_ocsp_req_deinit(r);
211 return ret;
212 }
213
214
215
216 /**
217 * Check if the provided OCSP response is usable for stapling in
218 * connections to this server. Returns GNUTLS_E_SUCCESS if yes.
219 *
220 * Supports only one certificate status per response.
221 *
222 * If expiry is not NULL, it will be set to the nextUpdate time
223 * contained in the response, or zero if the response does not contain
224 * a nextUpdate field.
225 *
226 * If nonce is not NULL, the response must contain a matching nonce.
227 */
228 int check_ocsp_response(server_rec *s, const gnutls_datum_t *ocsp_response,
229 apr_time_t* expiry, const gnutls_datum_t *nonce)
230 __attribute__((nonnull(1, 2)));
check_ocsp_response(server_rec * s,const gnutls_datum_t * ocsp_response,apr_time_t * expiry,const gnutls_datum_t * nonce)231 int check_ocsp_response(server_rec *s, const gnutls_datum_t *ocsp_response,
232 apr_time_t* expiry, const gnutls_datum_t *nonce)
233 {
234 mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
235 ap_get_module_config(s->module_config, &gnutls_module);
236
237 if (sc->ocsp->trust == NULL)
238 {
239 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
240 "No OCSP trust list available for server \"%s\"!",
241 s->server_hostname);
242 return GNUTLS_E_NO_CERTIFICATE_FOUND;
243 }
244
245 gnutls_ocsp_resp_t resp;
246 int ret = gnutls_ocsp_resp_init(&resp);
247 if (ret != GNUTLS_E_SUCCESS)
248 {
249 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
250 "Could not initialize OCSP response structure: %s (%d)",
251 gnutls_strerror(ret), ret);
252 goto resp_cleanup;
253 }
254 ret = gnutls_ocsp_resp_import(resp, ocsp_response);
255 if (ret != GNUTLS_E_SUCCESS)
256 {
257 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
258 "Importing OCSP response failed: %s (%d)",
259 gnutls_strerror(ret), ret);
260 goto resp_cleanup;
261 }
262
263 ret = gnutls_ocsp_resp_check_crt(resp, 0, sc->certs_x509_crt_chain[0]);
264 if (ret != GNUTLS_E_SUCCESS)
265 {
266 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
267 "OCSP response is not for server certificate: %s (%d)",
268 gnutls_strerror(ret), ret);
269 goto resp_cleanup;
270 }
271
272 unsigned int verify;
273 ret = gnutls_ocsp_resp_verify(resp, *(sc->ocsp->trust), &verify, 0);
274 if (ret != GNUTLS_E_SUCCESS)
275 {
276 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
277 "OCSP response verification failed: %s (%d)",
278 gnutls_strerror(ret), ret);
279 goto resp_cleanup;
280 }
281 else
282 {
283 /* verification worked, check the result */
284 if (verify != 0)
285 {
286 _log_verify_fail_reason(verify, s);
287 ret = GNUTLS_E_OCSP_RESPONSE_ERROR;
288 goto resp_cleanup;
289 }
290 else
291 ap_log_error(APLOG_MARK, APLOG_TRACE1, APR_SUCCESS, s,
292 "OCSP response signature is valid.");
293 }
294
295 /* Even some large CAs do not support nonces, probably because
296 * that way they can cache responses. :-/ */
297 if (nonce != NULL && sc->ocsp_check_nonce)
298 {
299 gnutls_datum_t resp_nonce;
300 ret = gnutls_ocsp_resp_get_nonce(resp, 0, &resp_nonce);
301 if (ret != GNUTLS_E_SUCCESS)
302 {
303 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
304 "Could not get OCSP response nonce: %s (%d)",
305 gnutls_strerror(ret), ret);
306 goto resp_cleanup;
307 }
308 if (resp_nonce.size != nonce->size
309 || memcmp(resp_nonce.data, nonce->data, nonce->size))
310 {
311 ret = GNUTLS_E_OCSP_RESPONSE_ERROR;
312 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
313 "OCSP response invalid: nonce mismatch");
314 gnutls_free(resp_nonce.data);
315 goto resp_cleanup;
316 }
317 ap_log_error(APLOG_MARK, APLOG_TRACE2, APR_SUCCESS, s,
318 "OCSP response: nonce match");
319 gnutls_free(resp_nonce.data);
320 }
321
322 /* OK, response is for our certificate and valid, let's get the
323 * actual response data. */
324 unsigned int cert_status;
325 time_t this_update;
326 time_t next_update;
327 ret = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL, NULL,
328 &cert_status, &this_update,
329 &next_update, NULL, NULL);
330 if (ret != GNUTLS_E_SUCCESS)
331 {
332 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
333 "Could not get OCSP response data: %s (%d)",
334 gnutls_strerror(ret), ret);
335 goto resp_cleanup;
336 }
337
338 apr_time_t now = apr_time_now();
339 apr_time_t valid_at;
340 apr_time_ansi_put(&valid_at, this_update);
341 /* Buffer for human-readable times produced by apr_rfc822_date,
342 * see apr_time.h */
343 char date_str[APR_RFC822_DATE_LEN];
344 apr_rfc822_date(date_str, valid_at);
345
346 if (now < valid_at)
347 {
348 /* We don't know if our clock or that of the OCSP responder is
349 * out of sync, so warn but continue. */
350 ap_log_error(APLOG_MARK, APLOG_WARNING, APR_EGENERAL, s,
351 "OSCP response claims to be from future (%s), check "
352 "time synchronization!", date_str);
353 }
354
355 if (next_update == (time_t) -1)
356 {
357 ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, s,
358 "OSCP response does not contain nextUpdate info.");
359 if (expiry != NULL)
360 *expiry = 0;
361 }
362 else
363 {
364 apr_time_t valid_to;
365 apr_time_ansi_put(&valid_to, next_update);
366 if (expiry != NULL)
367 *expiry = valid_to;
368 if (now > valid_to)
369 {
370 apr_rfc822_date(date_str, valid_to);
371 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
372 "OCSP response has expired at %s!", date_str);
373 /* Do not send a stale response */
374 ret = GNUTLS_E_OCSP_RESPONSE_ERROR;
375 goto resp_cleanup;
376 }
377 }
378
379 /* What's the actual status? Will be one of
380 * gnutls_ocsp_cert_status_t as defined in gnutls/ocsp.h. */
381 if (cert_status == GNUTLS_OCSP_CERT_GOOD)
382 {
383 /* Yay, everything's good! */
384 ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, s,
385 "CA flagged certificate as valid at %s.", date_str);
386 }
387 else
388 {
389 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
390 "CA flagged certificate as %s at %s.",
391 cert_status == GNUTLS_OCSP_CERT_REVOKED ?
392 "revoked" : "unknown", date_str);
393 ret = GNUTLS_E_OCSP_RESPONSE_ERROR;
394 }
395
396 resp_cleanup:
397 gnutls_ocsp_resp_deinit(resp);
398 return ret;
399 }
400
401
402
403 /*
404 * Returns the certificate fingerprint, memory is allocated from p.
405 */
mgs_get_cert_fingerprint(apr_pool_t * p,gnutls_x509_crt_t cert)406 static gnutls_datum_t mgs_get_cert_fingerprint(apr_pool_t *p,
407 gnutls_x509_crt_t cert)
408 {
409 gnutls_datum_t fingerprint = {NULL, 0};
410 size_t fplen = 0;
411 gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, NULL, &fplen);
412 unsigned char * fp = apr_palloc(p, fplen);
413 gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, fp, &fplen);
414 /* Safe integer type conversion: The types of fingerprint.size
415 * (unsigned int) and fplen (size_t) may have different
416 * lengths. */
417 #if defined(__GNUC__) && __GNUC__ < 5 && \
418 !(defined(__clang__) && __has_builtin(__builtin_add_overflow))
419 if (__builtin_expect(fplen <= UINT_MAX, 1))
420 {
421 fingerprint.size = (unsigned int) fplen;
422 fingerprint.data = fp;
423 }
424 #else
425 if (__builtin_add_overflow(fplen, 0, &fingerprint.size))
426 fingerprint.size = 0;
427 else
428 fingerprint.data = fp;
429 #endif
430 return fingerprint;
431 }
432
433
434
435 static apr_status_t do_ocsp_request(apr_pool_t *p, server_rec *s,
436 gnutls_datum_t *request,
437 gnutls_datum_t *response)
438 __attribute__((nonnull));
do_ocsp_request(apr_pool_t * p,server_rec * s,gnutls_datum_t * request,gnutls_datum_t * response)439 static apr_status_t do_ocsp_request(apr_pool_t *p, server_rec *s,
440 gnutls_datum_t *request,
441 gnutls_datum_t *response)
442 {
443 mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
444 ap_get_module_config(s->module_config, &gnutls_module);
445
446 if (apr_strnatcmp(sc->ocsp->uri->scheme, "http"))
447 {
448 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
449 "Scheme \"%s\" is not supported for OCSP requests!",
450 sc->ocsp->uri->scheme);
451 return APR_EINVAL;
452 }
453
454 const char* header = http_post_header(p, sc->ocsp->uri,
455 OCSP_REQ_TYPE, OCSP_RESP_TYPE,
456 request->size);
457 ap_log_error(APLOG_MARK, APLOG_TRACE2, APR_SUCCESS, s,
458 "OCSP POST header: %s", header);
459
460 /* Find correct port */
461 apr_port_t port = sc->ocsp->uri->port ?
462 sc->ocsp->uri->port : apr_uri_port_of_scheme(sc->ocsp->uri->scheme);
463
464 apr_sockaddr_t *sa;
465 apr_status_t rv = apr_sockaddr_info_get(&sa, sc->ocsp->uri->hostname,
466 APR_UNSPEC, port, 0, p);
467 if (rv != APR_SUCCESS)
468 {
469 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
470 "Address resolution for OCSP responder %s failed.",
471 sc->ocsp->uri->hostinfo);
472 }
473
474 /* There may be multiple answers, try them in order until one
475 * works. */
476 apr_socket_t *sock;
477 while (sa)
478 {
479 rv = apr_socket_create(&sock, sa->family, SOCK_STREAM,
480 APR_PROTO_TCP, p);
481 if (rv == APR_SUCCESS)
482 {
483 apr_socket_timeout_set(sock, sc->ocsp_socket_timeout);
484 rv = apr_socket_connect(sock, sa);
485 if (rv == APR_SUCCESS)
486 /* Connected! */
487 break;
488 apr_socket_close(sock);
489 }
490 sa = sa->next;
491 }
492 /* If the socket is connected, 'sa' points at the matching
493 * address. */
494 if (sa == NULL)
495 {
496 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
497 "Connecting to OCSP responder %s failed.",
498 sc->ocsp->uri->hostinfo);
499 return rv;
500 }
501
502 /* Header is generated locally, so strlen() is safe. */
503 rv = sock_send_buf(sock, header, strlen(header));
504 if (rv == APR_SUCCESS)
505 rv = sock_send_buf(sock, (char*) request->data, request->size);
506 /* catches errors from both header and request */
507 if (rv != APR_SUCCESS)
508 {
509 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
510 "Sending OCSP request failed.");
511 goto exit;
512 }
513
514 /* Prepare bucket brigades to read the response header. BBs make
515 * it easy to split the header into lines. */
516 apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
517 apr_bucket_brigade *bb = apr_brigade_create(p, ba);
518 /* will carry split response headers */
519 apr_bucket_brigade *rh = apr_brigade_create(p, ba);
520
521 APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_socket_create(sock, ba));
522 /* The first line in the response header must be the status, check
523 * for OK status code. Line looks similar to "HTTP/1.0 200 OK". */
524 const char *h = read_line(p, bb, rh);
525 const char *code = 0;
526 if (h == NULL
527 || strncmp(h, "HTTP/", 5)
528 || (code = ap_strchr(h, ' ')) == NULL
529 || apr_atoi64(code + 1) != HTTP_OK)
530 {
531 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
532 "Invalid HTTP response status from %s: %s",
533 sc->ocsp->uri->hostinfo, h);
534 rv = APR_ECONNRESET;
535 goto exit;
536 }
537 /* Read remaining header lines */
538 for (h = read_line(p, bb, rh); h != NULL && apr_strnatcmp(h, "") != 0;
539 h = read_line(p, bb, rh))
540 {
541 ap_log_error(APLOG_MARK, APLOG_TRACE2, APR_SUCCESS, s,
542 "Received header: %s", h);
543 }
544 /* The last header line should be empty (""), NULL indicates an
545 * error. */
546 if (h == NULL)
547 {
548 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
549 "Error while reading HTTP response header from %s",
550 sc->ocsp->uri->hostinfo);
551 rv = APR_ECONNRESET;
552 goto exit;
553 }
554
555 /* Headers have been consumed, the rest of the available data
556 * should be the actual response. */
557 apr_size_t len = OCSP_RESP_SIZE_MAX;
558 char buf[OCSP_RESP_SIZE_MAX];
559 /* apr_brigade_pflatten() can allocate directly from the pool, but
560 * the documentation does not describe a way to limit the size of
561 * the buffer, which is necessary here to prevent DoS by endless
562 * response. Use apr_brigade_flatten() to read to a stack pool,
563 * then create a copy to return. */
564 rv = apr_brigade_flatten(bb, buf, &len);
565 if (rv != APR_SUCCESS)
566 {
567 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
568 "Failed to read OCSP response.");
569 goto exit;
570 }
571
572 /* With the length restriction this really should not overflow. */
573 #if defined(__GNUC__) && __GNUC__ < 5 && \
574 !(defined(__clang__) && __has_builtin(__builtin_add_overflow))
575 if (__builtin_expect(len > UINT_MAX, 0))
576 #else
577 if (__builtin_add_overflow(len, 0, &response->size))
578 #endif
579 {
580 response->data = NULL;
581 rv = APR_ENOMEM;
582 }
583 else
584 {
585 #if defined(__GNUC__) && __GNUC__ < 5 && \
586 !(defined(__clang__) && __has_builtin(__builtin_add_overflow))
587 response->size = (unsigned int) len;
588 #endif
589 response->data = apr_pmemdup(p, buf, len);
590 }
591
592 exit:
593 apr_socket_close(sock);
594 return rv;
595 }
596
597
598
mgs_cache_ocsp_response(server_rec * s)599 apr_status_t mgs_cache_ocsp_response(server_rec *s)
600 {
601 mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
602 ap_get_module_config(s->module_config, &gnutls_module);
603
604 if (sc->cache == NULL)
605 {
606 /* OCSP caching requires a cache. */
607 return APR_ENOTIMPL;
608 }
609
610 apr_pool_t *tmp;
611 apr_status_t rv = apr_pool_create(&tmp, NULL);
612 if (rv != APR_SUCCESS)
613 {
614 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
615 "could not create temporary pool for %s",
616 __func__);
617 return rv;
618 }
619
620 gnutls_datum_t resp;
621 gnutls_datum_t nonce = { NULL, 0 };
622
623 if (sc->ocsp_response_file != NULL)
624 {
625 ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, s,
626 "Loading OCSP response from %s",
627 sc->ocsp_response_file);
628 rv = datum_from_file(tmp, sc->ocsp_response_file, &resp);
629 if (rv != APR_SUCCESS)
630 {
631 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
632 "Loading OCSP response from %s failed!",
633 sc->ocsp_response_file);
634 apr_pool_destroy(tmp);
635 return rv;
636 }
637 }
638 else
639 {
640 gnutls_datum_t req;
641 int ret = mgs_create_ocsp_request(s, &req, &nonce);
642 if (ret == GNUTLS_E_SUCCESS)
643 {
644 ap_log_error(APLOG_MARK, APLOG_TRACE2, APR_SUCCESS, s,
645 "created OCSP request for %s:%d: %s",
646 s->server_hostname, s->addrs->host_port,
647 apr_pescape_hex(tmp, req.data, req.size, 0));
648 }
649 else
650 {
651 gnutls_free(req.data);
652 gnutls_free(nonce.data);
653 apr_pool_destroy(tmp);
654 return APR_EGENERAL;
655 }
656
657 rv = do_ocsp_request(tmp, s, &req, &resp);
658 gnutls_free(req.data);
659 if (rv != APR_SUCCESS)
660 {
661 /* do_ocsp_request() does its own error logging. */
662 gnutls_free(nonce.data);
663 apr_pool_destroy(tmp);
664 return rv;
665 }
666 }
667
668 apr_time_t next_update;
669 if (check_ocsp_response(s, &resp, &next_update, nonce.size ? &nonce : NULL)
670 != GNUTLS_E_SUCCESS)
671 {
672 ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_EGENERAL, s,
673 "OCSP response validation failed, cannot "
674 "update cache.");
675 apr_pool_destroy(tmp);
676 gnutls_free(nonce.data);
677 return APR_EGENERAL;
678 }
679 gnutls_free(nonce.data);
680
681 apr_time_t expiry = apr_time_now() + sc->ocsp_cache_time;
682 /* Make sure that a response is not cached beyond its nextUpdate
683 * time. If the variable next_update is zero, the response does
684 * not contain a nextUpdate field. */
685 if (next_update != 0 && next_update < expiry)
686 {
687 char date_str[APR_RFC822_DATE_LEN];
688 apr_rfc822_date(date_str, next_update);
689 ap_log_error(APLOG_MARK, APLOG_WARNING, APR_EGENERAL, s,
690 "OCSP response timeout restricted to nextUpdate time %s. "
691 "Check if GnuTLSOCSPCacheTimeout is appropriate.",
692 date_str);
693 expiry = next_update;
694 }
695
696 int r = sc->cache->store(s, sc->ocsp->fingerprint, resp, expiry);
697 /* destroy pool, and original copy of the OCSP response with it */
698 apr_pool_destroy(tmp);
699 if (r != 0)
700 {
701 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
702 "Storing OCSP response in cache failed.");
703 return APR_EGENERAL;
704 }
705 return APR_SUCCESS;
706 }
707
708
709
710 /*
711 * Retries after failed OCSP requests must be rate limited. If the
712 * responder is overloaded or buggy we don't want to add too much more
713 * load, and if a MITM is messing with requests a repetition loop
714 * might end up being a self-inflicted denial of service.
715 */
mgs_cache_ocsp_failure(server_rec * s)716 void mgs_cache_ocsp_failure(server_rec *s)
717 {
718 mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
719 ap_get_module_config(s->module_config, &gnutls_module);
720
721 unsigned char c = OCSP_FAILURE_CACHE_DATA;
722 gnutls_datum_t dummy = {
723 .data = &c,
724 .size = sizeof(c)
725 };
726 apr_time_t expiry = apr_time_now() + sc->ocsp_failure_timeout;
727
728 char date_str[APR_RFC822_DATE_LEN];
729 apr_rfc822_date(date_str, expiry);
730 ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
731 "OCSP request for %s failed, next try after %s.",
732 s->server_hostname, date_str);
733
734 int r = sc->cache->store(s, sc->ocsp->fingerprint, dummy, expiry);
735 if (r != 0)
736 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
737 "Caching OCSP failure failed.");
738 }
739
740
741
mgs_get_ocsp_response(gnutls_session_t session,void * ptr,gnutls_datum_t * ocsp_response)742 int mgs_get_ocsp_response(gnutls_session_t session,
743 void *ptr __attribute__((unused)),
744 gnutls_datum_t *ocsp_response)
745 {
746 mgs_handle_t *ctxt = gnutls_session_get_ptr(session);
747 mgs_srvconf_rec *sc = ctxt->sc;
748
749 if (!sc->ocsp_staple || sc->cache == NULL)
750 {
751 /* OCSP must be enabled and caching requires a cache. */
752 return GNUTLS_E_NO_CERTIFICATE_STATUS;
753 }
754
755 *ocsp_response = sc->cache->fetch(ctxt,
756 sc->ocsp->fingerprint);
757 if (ocsp_response->size == 0)
758 {
759 ap_log_cerror(APLOG_MARK, APLOG_TRACE1, APR_EGENERAL, ctxt->c,
760 "Fetching OCSP response from cache failed.");
761 }
762 else if ((ocsp_response->size == sizeof(unsigned char)) &&
763 (*((unsigned char *) ocsp_response->data) == OCSP_FAILURE_CACHE_DATA))
764 {
765 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_EGENERAL, ctxt->c,
766 "Cached OCSP failure found for %s.",
767 ctxt->c->base_server->server_hostname);
768 goto fail_cleanup;
769 }
770 else
771 {
772 return GNUTLS_E_SUCCESS;
773 }
774 /* get rid of invalid response (if any) */
775 gnutls_free(ocsp_response->data);
776 ocsp_response->data = NULL;
777
778 /* If the cache had no response or an invalid one, try to update. */
779 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ctxt->c,
780 "No valid OCSP response in cache, trying to update.");
781
782 apr_status_t rv = apr_global_mutex_trylock(sc->ocsp_mutex);
783 if (APR_STATUS_IS_EBUSY(rv))
784 {
785 /* Another thread is currently holding the mutex, wait. */
786 apr_global_mutex_lock(sc->ocsp_mutex);
787 /* Check if this other thread updated the response we need. It
788 * would be better to have a vhost specific mutex, but at the
789 * moment there's no good way to integrate that with the
790 * Apache Mutex directive. */
791 *ocsp_response = sc->cache->fetch(ctxt,
792 sc->ocsp->fingerprint);
793 if (ocsp_response->size > 0)
794 {
795 /* Got a valid response now, unlock mutex and return. */
796 apr_global_mutex_unlock(sc->ocsp_mutex);
797 return GNUTLS_E_SUCCESS;
798 }
799 else
800 {
801 gnutls_free(ocsp_response->data);
802 ocsp_response->data = NULL;
803 }
804 }
805
806 rv = mgs_cache_ocsp_response(ctxt->c->base_server);
807 if (rv != APR_SUCCESS)
808 {
809 ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, ctxt->c,
810 "Caching a fresh OCSP response failed");
811 /* cache failure to rate limit retries */
812 mgs_cache_ocsp_failure(ctxt->c->base_server);
813 apr_global_mutex_unlock(sc->ocsp_mutex);
814 goto fail_cleanup;
815 }
816 apr_global_mutex_unlock(sc->ocsp_mutex);
817
818 /* retry reading from cache */
819 *ocsp_response = sc->cache->fetch(ctxt,
820 sc->ocsp->fingerprint);
821 if (ocsp_response->size == 0)
822 {
823 ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c,
824 "Fetching OCSP response from cache failed on retry.");
825 }
826 else
827 {
828 return GNUTLS_E_SUCCESS;
829 }
830
831 /* failure, clean up response data */
832 fail_cleanup:
833 gnutls_free(ocsp_response->data);
834 ocsp_response->size = 0;
835 ocsp_response->data = NULL;
836 return GNUTLS_E_NO_CERTIFICATE_STATUS;
837 }
838
839
840
mgs_create_ocsp_trust_list(gnutls_x509_trust_list_t * tl,const gnutls_x509_crt_t * chain,const int num)841 int mgs_create_ocsp_trust_list(gnutls_x509_trust_list_t *tl,
842 const gnutls_x509_crt_t *chain,
843 const int num)
844 {
845 int added = 0;
846 int ret = gnutls_x509_trust_list_init(tl, num);
847
848 if (ret == GNUTLS_E_SUCCESS)
849 added = gnutls_x509_trust_list_add_cas(*tl, chain, num, 0);
850
851 if (added != num)
852 ret = GNUTLS_E_CERTIFICATE_ERROR;
853
854 /* Clean up trust list in case of error */
855 if (ret != GNUTLS_E_SUCCESS)
856 gnutls_x509_trust_list_deinit(*tl, 0);
857
858 return ret;
859 }
860
861
862
mgs_cleanup_trust_list(void * data)863 apr_status_t mgs_cleanup_trust_list(void *data)
864 {
865 gnutls_x509_trust_list_t *tl = (gnutls_x509_trust_list_t *) data;
866 gnutls_x509_trust_list_deinit(*tl, 0);
867 return APR_SUCCESS;
868 }
869
870
871
mgs_cert_get_ocsp_uri(apr_pool_t * p,gnutls_x509_crt_t cert)872 apr_uri_t * mgs_cert_get_ocsp_uri(apr_pool_t *p, gnutls_x509_crt_t cert)
873 {
874 apr_pool_t *tmp;
875 apr_status_t rv = apr_pool_create(&tmp, p);
876 if (rv != APR_SUCCESS)
877 return NULL;
878
879 apr_uri_t *ocsp_uri = NULL;
880
881 int ret = GNUTLS_E_SUCCESS;
882 /* search authority info access for OCSP URI */
883 for (int seq = 0; ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; seq++)
884 {
885 gnutls_datum_t ocsp_access_data;
886 ret = gnutls_x509_crt_get_authority_info_access(cert, seq,
887 GNUTLS_IA_OCSP_URI,
888 &ocsp_access_data,
889 NULL);
890 if (ret == GNUTLS_E_SUCCESS)
891 {
892 /* create NULL terminated string */
893 char *ocsp_str =
894 apr_pstrndup(tmp, (const char*) ocsp_access_data.data,
895 ocsp_access_data.size);
896 gnutls_free(ocsp_access_data.data);
897
898 ocsp_uri = apr_palloc(p, sizeof(apr_uri_t));
899 rv = apr_uri_parse(p, ocsp_str, ocsp_uri);
900 if (rv == APR_SUCCESS)
901 break;
902 else
903 ocsp_uri = NULL;
904 }
905 }
906
907 apr_pool_destroy(tmp);
908 return ocsp_uri;
909 }
910
911
912
913 /*
914 * Like in the general post_config hook the HTTP status codes for
915 * errors are just for fun. What matters is "neither OK nor DECLINED"
916 * to denote an error.
917 */
mgs_ocsp_post_config_server(apr_pool_t * pconf,apr_pool_t * ptemp,server_rec * server)918 int mgs_ocsp_post_config_server(apr_pool_t *pconf,
919 apr_pool_t *ptemp __attribute__((unused)),
920 server_rec *server)
921 {
922 mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
923 ap_get_module_config(server->module_config, &gnutls_module);
924
925 if (sc->certs_x509_chain_num < 2)
926 {
927 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, server,
928 "OCSP stapling is enabled but no CA certificate "
929 "available for %s:%d, make sure it is included in "
930 "GnuTLSCertificateFile!",
931 server->server_hostname, server->addrs->host_port);
932 return HTTP_NOT_FOUND;
933 }
934
935 /* set default values for unset parameters */
936 if (sc->ocsp_check_nonce == GNUTLS_ENABLED_UNSET)
937 sc->ocsp_check_nonce = GNUTLS_ENABLED_TRUE;
938 if (sc->ocsp_cache_time == MGS_TIMEOUT_UNSET)
939 sc->ocsp_cache_time = apr_time_from_sec(MGS_OCSP_CACHE_TIMEOUT);
940 if (sc->ocsp_failure_timeout == MGS_TIMEOUT_UNSET)
941 sc->ocsp_failure_timeout = apr_time_from_sec(MGS_OCSP_FAILURE_TIMEOUT);
942 if (sc->ocsp_socket_timeout == MGS_TIMEOUT_UNSET)
943 sc->ocsp_socket_timeout = apr_time_from_sec(MGS_OCSP_SOCKET_TIMEOUT);
944
945 sc->ocsp = apr_palloc(pconf, sizeof(struct mgs_ocsp_data));
946
947 sc->ocsp->fingerprint =
948 mgs_get_cert_fingerprint(pconf, sc->certs_x509_crt_chain[0]);
949 if (sc->ocsp->fingerprint.data == NULL)
950 return HTTP_INTERNAL_SERVER_ERROR;
951
952 sc->ocsp->uri = mgs_cert_get_ocsp_uri(pconf,
953 sc->certs_x509_crt_chain[0]);
954 if (sc->ocsp->uri == NULL && sc->ocsp_response_file == NULL)
955 {
956 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, server,
957 "OCSP stapling is enabled for for %s:%d, but there is "
958 "neither an OCSP URI in the certificate nor a "
959 "GnuTLSOCSPResponseFile setting for this host!",
960 server->server_hostname, server->addrs->host_port);
961 return HTTP_NOT_FOUND;
962 }
963
964 sc->ocsp->trust = apr_palloc(pconf,
965 sizeof(gnutls_x509_trust_list_t));
966 /* Only the direct issuer may sign the OCSP response or an OCSP
967 * signer. */
968 int ret = mgs_create_ocsp_trust_list(sc->ocsp->trust,
969 &(sc->certs_x509_crt_chain[1]),
970 1);
971 if (ret != GNUTLS_E_SUCCESS)
972 {
973 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, server,
974 "Could not create OCSP trust list: %s (%d)",
975 gnutls_strerror(ret), ret);
976 return HTTP_INTERNAL_SERVER_ERROR;
977 }
978 /* deinit trust list when the config pool is destroyed */
979 apr_pool_cleanup_register(pconf, sc->ocsp->trust,
980 mgs_cleanup_trust_list,
981 apr_pool_cleanup_null);
982
983 /* enable status request callback */
984 gnutls_certificate_set_ocsp_status_request_function(sc->certs,
985 mgs_get_ocsp_response,
986 sc);
987
988 return OK;
989 }
990