source: mod_gnutls/src/gnutls_ocsp.c @ ef107fd

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

Remove TODO for OCSP requests without nonces

Ideally all OCSP responders should support nonces. A new comment
describes how to implement disabling nonce verification if someone
needs to (could become an option similar to the one in mod_ssl).

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