source: mod_gnutls/src/gnutls_ocsp.c @ c6dda6d

debian/masterdebian/stretch-backportsupstream
Last change on this file since c6dda6d was c6dda6d, checked in by Thomas Klute <thomas2.klute@…>, 3 years ago

Rate limit OCSP requests

Retries after failed OCSP requests must be rate limited. If the
responder is overloaded or buggy we don't want to add too much more
load, and if a MITM is messing with requests a repetition loop might
end up being a self-inflicted denial of service.

The minimum time to wait between retries can be configured using the
GnuTLSOCSPFailureTimeout directive.

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