source: mod_gnutls/src/gnutls_ocsp.c @ b888e8b

debian/masterdebian/stretch-backportsproxy-ticketupstream
Last change on this file since b888e8b was b888e8b, checked in by Thomas Klute <thomas2.klute@…>, 4 years ago

New directive GnuTLSOCSPCheckNonce

Some CAs refuse to send nonces in their OCSP responses, probably
because that way they can cache responses. This makes nonce
verification fail, so give the user an option disable it.

  • Property mode set to 100644
File size: 32.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_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
30APLOG_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 */
48static 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
74const 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
91const 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
108const 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 */
129static int mgs_create_ocsp_request(server_rec *s, gnutls_datum_t *req,
130                            gnutls_datum_t *nonce)
131    __attribute__((nonnull(1, 2)));
132static 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 */
228int 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)));
231int 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 */
406static 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 && !defined(__clang__)
418    if (__builtin_expect(fplen <= UINT_MAX, 1))
419    {
420        fingerprint.size = (unsigned int) fplen;
421        fingerprint.data = fp;
422    }
423#else
424    if (__builtin_add_overflow(fplen, 0, &fingerprint.size))
425        fingerprint.size = 0;
426    else
427        fingerprint.data = fp;
428#endif
429    return fingerprint;
430}
431
432
433
434static apr_status_t do_ocsp_request(apr_pool_t *p, server_rec *s,
435                                    gnutls_datum_t *request,
436                                    gnutls_datum_t *response)
437    __attribute__((nonnull));
438static apr_status_t do_ocsp_request(apr_pool_t *p, server_rec *s,
439                                    gnutls_datum_t *request,
440                                    gnutls_datum_t *response)
441{
442    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
443        ap_get_module_config(s->module_config, &gnutls_module);
444
445    if (apr_strnatcmp(sc->ocsp->uri->scheme, "http"))
446    {
447        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
448                     "Scheme \"%s\" is not supported for OCSP requests!",
449                     sc->ocsp->uri->scheme);
450        return APR_EINVAL;
451    }
452
453    const char* header = http_post_header(p, sc->ocsp->uri,
454                                          OCSP_REQ_TYPE, OCSP_RESP_TYPE,
455                                          request->size);
456    ap_log_error(APLOG_MARK, APLOG_TRACE2, APR_SUCCESS, s,
457                 "OCSP POST header: %s", header);
458
459    /* Find correct port */
460    apr_port_t port = sc->ocsp->uri->port ?
461        sc->ocsp->uri->port : apr_uri_port_of_scheme(sc->ocsp->uri->scheme);
462
463    apr_sockaddr_t *sa;
464    apr_status_t rv = apr_sockaddr_info_get(&sa, sc->ocsp->uri->hostname,
465                                            APR_UNSPEC, port, 0, p);
466    if (rv != APR_SUCCESS)
467    {
468        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
469                     "Address resolution for OCSP responder %s failed.",
470                     sc->ocsp->uri->hostinfo);
471    }
472
473    /* There may be multiple answers, try them in order until one
474     * works. */
475    apr_socket_t *sock;
476    while (sa)
477    {
478        rv = apr_socket_create(&sock, sa->family, SOCK_STREAM,
479                               APR_PROTO_TCP, p);
480        if (rv == APR_SUCCESS)
481        {
482            apr_socket_timeout_set(sock, sc->ocsp_socket_timeout);
483            rv = apr_socket_connect(sock, sa);
484            if (rv == APR_SUCCESS)
485                /* Connected! */
486                break;
487            apr_socket_close(sock);
488        }
489        sa = sa->next;
490    }
491    /* If the socket is connected, 'sa' points at the matching
492     * address. */
493    if (sa == NULL)
494    {
495        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
496                     "Connecting to OCSP responder %s failed.",
497                     sc->ocsp->uri->hostinfo);
498        return rv;
499    }
500
501    /* Header is generated locally, so strlen() is safe. */
502    rv = sock_send_buf(sock, header, strlen(header));
503    if (rv == APR_SUCCESS)
504        rv = sock_send_buf(sock, (char*) request->data, request->size);
505    /* catches errors from both header and request */
506    if (rv != APR_SUCCESS)
507    {
508        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
509                     "Sending OCSP request failed.");
510        goto exit;
511    }
512
513    /* Prepare bucket brigades to read the response header. BBs make
514     * it easy to split the header into lines. */
515    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
516    apr_bucket_brigade *bb = apr_brigade_create(p, ba);
517    /* will carry split response headers */
518    apr_bucket_brigade *rh = apr_brigade_create(p, ba);
519
520    APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_socket_create(sock, ba));
521    /* The first line in the response header must be the status, check
522     * for OK status code. Line looks similar to "HTTP/1.0 200 OK". */
523    const char *h = read_line(p, bb, rh);
524    const char *code = 0;
525    if (h == NULL
526        || strncmp(h, "HTTP/", 5)
527        || (code = ap_strchr(h, ' ')) == NULL
528        || apr_atoi64(code + 1) != HTTP_OK)
529    {
530        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
531                     "Invalid HTTP response status from %s: %s",
532                     sc->ocsp->uri->hostinfo, h);
533        rv = APR_ECONNRESET;
534        goto exit;
535    }
536    /* Read remaining header lines */
537    for (h = read_line(p, bb, rh); h != NULL && apr_strnatcmp(h, "") != 0;
538         h = read_line(p, bb, rh))
539    {
540        ap_log_error(APLOG_MARK, APLOG_TRACE2, APR_SUCCESS, s,
541                     "Received header: %s", h);
542    }
543    /* The last header line should be empty (""), NULL indicates an
544     * error. */
545    if (h == NULL)
546    {
547        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
548                     "Error while reading HTTP response header from %s",
549                     sc->ocsp->uri->hostinfo);
550        rv = APR_ECONNRESET;
551        goto exit;
552    }
553
554    /* Headers have been consumed, the rest of the available data
555     * should be the actual response. */
556    apr_size_t len = OCSP_RESP_SIZE_MAX;
557    char buf[OCSP_RESP_SIZE_MAX];
558    /* apr_brigade_pflatten() can allocate directly from the pool, but
559     * the documentation does not describe a way to limit the size of
560     * the buffer, which is necessary here to prevent DoS by endless
561     * response. Use apr_brigade_flatten() to read to a stack pool,
562     * then create a copy to return. */
563    rv = apr_brigade_flatten(bb, buf, &len);
564    if (rv != APR_SUCCESS)
565    {
566        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
567                     "Failed to read OCSP response.");
568        goto exit;
569    }
570
571    /* With the length restriction this really should not overflow. */
572#if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__)
573    if (__builtin_expect(len > UINT_MAX, 0))
574#else
575    if (__builtin_add_overflow(len, 0, &response->size))
576#endif
577    {
578        response->data = NULL;
579        rv = APR_ENOMEM;
580    }
581    else
582    {
583#if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__)
584        response->size = (unsigned int) len;
585#endif
586        response->data = apr_pmemdup(p, buf, len);
587    }
588
589 exit:
590    apr_socket_close(sock);
591    return rv;
592}
593
594
595
596apr_status_t mgs_cache_ocsp_response(server_rec *s)
597{
598    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
599        ap_get_module_config(s->module_config, &gnutls_module);
600
601    if (sc->cache == NULL)
602    {
603        /* OCSP caching requires a cache. */
604        return APR_ENOTIMPL;
605    }
606
607    apr_pool_t *tmp;
608    apr_status_t rv = apr_pool_create(&tmp, NULL);
609    if (rv != APR_SUCCESS)
610    {
611        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
612                     "could not create temporary pool for %s",
613                     __func__);
614        return rv;
615    }
616
617    gnutls_datum_t resp;
618    gnutls_datum_t nonce = { NULL, 0 };
619
620    if (sc->ocsp_response_file != NULL)
621    {
622        ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, s,
623                     "Loading OCSP response from %s",
624                     sc->ocsp_response_file);
625        rv = datum_from_file(tmp, sc->ocsp_response_file, &resp);
626        if (rv != APR_SUCCESS)
627        {
628            ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
629                         "Loading OCSP response from %s failed!",
630                         sc->ocsp_response_file);
631            apr_pool_destroy(tmp);
632            return rv;
633        }
634    }
635    else
636    {
637        gnutls_datum_t req;
638        int ret = mgs_create_ocsp_request(s, &req, &nonce);
639        if (ret == GNUTLS_E_SUCCESS)
640        {
641            ap_log_error(APLOG_MARK, APLOG_TRACE2, APR_SUCCESS, s,
642                         "created OCSP request for %s:%d: %s",
643                         s->server_hostname, s->addrs->host_port,
644                         apr_pescape_hex(tmp, req.data, req.size, 0));
645        }
646        else
647        {
648            gnutls_free(req.data);
649            gnutls_free(nonce.data);
650            apr_pool_destroy(tmp);
651            return APR_EGENERAL;
652        }
653
654        rv = do_ocsp_request(tmp, s, &req, &resp);
655        gnutls_free(req.data);
656        if (rv != APR_SUCCESS)
657        {
658            /* do_ocsp_request() does its own error logging. */
659            gnutls_free(nonce.data);
660            apr_pool_destroy(tmp);
661            return rv;
662        }
663    }
664
665    apr_time_t expiry;
666    if (check_ocsp_response(s, &resp, &expiry, nonce.size ? &nonce : NULL)
667        != GNUTLS_E_SUCCESS)
668    {
669        ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_EGENERAL, s,
670                     "OCSP response validation failed, cannot "
671                     "update cache.");
672        apr_pool_destroy(tmp);
673        gnutls_free(nonce.data);
674        return APR_EGENERAL;
675    }
676    gnutls_free(nonce.data);
677
678    /* If expiry is zero, the response does not contain a nextUpdate
679     * field. Use the default cache timeout. */
680    if (expiry == 0)
681        expiry = apr_time_now() + sc->cache_timeout;
682    /* Apply grace time otherwise. */
683    else
684        expiry -= sc->ocsp_grace_time;
685
686    int r = sc->cache->store(s, sc->ocsp->fingerprint, resp, expiry);
687    /* destroy pool, and original copy of the OCSP response with it */
688    apr_pool_destroy(tmp);
689    if (r != 0)
690    {
691        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
692                      "Storing OCSP response in cache failed.");
693        return APR_EGENERAL;
694    }
695    return APR_SUCCESS;
696}
697
698
699
700/*
701 * Retries after failed OCSP requests must be rate limited. If the
702 * responder is overloaded or buggy we don't want to add too much more
703 * load, and if a MITM is messing with requests a repetition loop
704 * might end up being a self-inflicted denial of service.
705 */
706void mgs_cache_ocsp_failure(server_rec *s)
707{
708    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
709        ap_get_module_config(s->module_config, &gnutls_module);
710
711    unsigned char c = OCSP_FAILURE_CACHE_DATA;
712    gnutls_datum_t dummy = {
713        .data = &c,
714        .size = sizeof(c)
715    };
716    apr_time_t expiry = apr_time_now() + sc->ocsp_failure_timeout;
717
718    char date_str[APR_RFC822_DATE_LEN];
719    apr_rfc822_date(date_str, expiry);
720    ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
721                 "OCSP request for %s failed, next try after %s.",
722                 s->server_hostname, date_str);
723
724    int r = sc->cache->store(s, sc->ocsp->fingerprint, dummy, expiry);
725    if (r != 0)
726        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
727                     "Caching OCSP failure failed.");
728}
729
730
731
732int mgs_get_ocsp_response(gnutls_session_t session __attribute__((unused)),
733                          void *ptr,
734                          gnutls_datum_t *ocsp_response)
735{
736    mgs_handle_t *ctxt = (mgs_handle_t *) ptr;
737    if (!ctxt->sc->ocsp_staple || ctxt->sc->cache == NULL)
738    {
739        /* OCSP must be enabled and caching requires a cache. */
740        return GNUTLS_E_NO_CERTIFICATE_STATUS;
741    }
742
743    *ocsp_response = ctxt->sc->cache->fetch(ctxt,
744                                            ctxt->sc->ocsp->fingerprint);
745    if (ocsp_response->size == 0)
746    {
747        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, APR_EGENERAL, ctxt->c,
748                      "Fetching OCSP response from cache failed.");
749    }
750    else if ((ocsp_response->size == sizeof(unsigned char)) &&
751             (*((unsigned char *) ocsp_response->data) == OCSP_FAILURE_CACHE_DATA))
752    {
753        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_EGENERAL, ctxt->c,
754                      "Cached OCSP failure found for %s.",
755                      ctxt->c->base_server->server_hostname);
756        goto fail_cleanup;
757    }
758    else
759    {
760        return GNUTLS_E_SUCCESS;
761    }
762    /* get rid of invalid response (if any) */
763    gnutls_free(ocsp_response->data);
764    ocsp_response->data = NULL;
765
766    /* If the cache had no response or an invalid one, try to update. */
767    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ctxt->c,
768                  "No valid OCSP response in cache, trying to update.");
769
770    apr_status_t rv = apr_global_mutex_trylock(ctxt->sc->ocsp_mutex);
771    if (APR_STATUS_IS_EBUSY(rv))
772    {
773        /* Another thread is currently holding the mutex, wait. */
774        apr_global_mutex_lock(ctxt->sc->ocsp_mutex);
775        /* Check if this other thread updated the response we need. It
776         * would be better to have a vhost specific mutex, but at the
777         * moment there's no good way to integrate that with the
778         * Apache Mutex directive. */
779        *ocsp_response = ctxt->sc->cache->fetch(ctxt,
780                                                ctxt->sc->ocsp->fingerprint);
781        if (ocsp_response->size > 0)
782        {
783            /* Got a valid response now, unlock mutex and return. */
784            apr_global_mutex_unlock(ctxt->sc->ocsp_mutex);
785            return GNUTLS_E_SUCCESS;
786        }
787        else
788        {
789            gnutls_free(ocsp_response->data);
790            ocsp_response->data = NULL;
791        }
792    }
793
794    rv = mgs_cache_ocsp_response(ctxt->c->base_server);
795    if (rv != APR_SUCCESS)
796    {
797        ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, ctxt->c,
798                      "Caching a fresh OCSP response failed");
799        /* cache failure to rate limit retries */
800        mgs_cache_ocsp_failure(ctxt->c->base_server);
801        apr_global_mutex_unlock(ctxt->sc->ocsp_mutex);
802        goto fail_cleanup;
803    }
804    apr_global_mutex_unlock(ctxt->sc->ocsp_mutex);
805
806    /* retry reading from cache */
807    *ocsp_response = ctxt->sc->cache->fetch(ctxt,
808                                            ctxt->sc->ocsp->fingerprint);
809    if (ocsp_response->size == 0)
810    {
811        ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c,
812                      "Fetching OCSP response from cache failed on retry.");
813    }
814    else
815    {
816        return GNUTLS_E_SUCCESS;
817    }
818
819    /* failure, clean up response data */
820 fail_cleanup:
821    gnutls_free(ocsp_response->data);
822    ocsp_response->size = 0;
823    ocsp_response->data = NULL;
824    return GNUTLS_E_NO_CERTIFICATE_STATUS;
825}
826
827
828
829int mgs_create_ocsp_trust_list(gnutls_x509_trust_list_t *tl,
830                               const gnutls_x509_crt_t *chain,
831                               const int num)
832{
833    int added = 0;
834    int ret = gnutls_x509_trust_list_init(tl, num);
835
836    if (ret == GNUTLS_E_SUCCESS)
837        added = gnutls_x509_trust_list_add_cas(*tl, chain, num, 0);
838
839    if (added != num)
840        ret = GNUTLS_E_CERTIFICATE_ERROR;
841
842    /* Clean up trust list in case of error */
843    if (ret != GNUTLS_E_SUCCESS)
844        gnutls_x509_trust_list_deinit(*tl, 0);
845
846    return ret;
847}
848
849
850
851apr_status_t mgs_cleanup_trust_list(void *data)
852{
853    gnutls_x509_trust_list_t *tl = (gnutls_x509_trust_list_t *) data;
854    gnutls_x509_trust_list_deinit(*tl, 0);
855    return APR_SUCCESS;
856}
857
858
859
860apr_uri_t * mgs_cert_get_ocsp_uri(apr_pool_t *p, gnutls_x509_crt_t cert)
861{
862    apr_pool_t *tmp;
863    apr_status_t rv = apr_pool_create(&tmp, p);
864    if (rv != APR_SUCCESS)
865        return NULL;
866
867    apr_uri_t *ocsp_uri = NULL;
868
869    int ret = GNUTLS_E_SUCCESS;
870    /* search authority info access for OCSP URI */
871    for (int seq = 0; ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; seq++)
872    {
873        gnutls_datum_t ocsp_access_data;
874        ret = gnutls_x509_crt_get_authority_info_access(cert, seq,
875                                                        GNUTLS_IA_OCSP_URI,
876                                                        &ocsp_access_data,
877                                                        NULL);
878        if (ret == GNUTLS_E_SUCCESS)
879        {
880            /* create NULL terminated string */
881            char *ocsp_str =
882                apr_pstrndup(tmp, (const char*) ocsp_access_data.data,
883                             ocsp_access_data.size);
884            gnutls_free(ocsp_access_data.data);
885
886            ocsp_uri = apr_palloc(p, sizeof(apr_uri_t));
887            rv = apr_uri_parse(p, ocsp_str, ocsp_uri);
888            if (rv == APR_SUCCESS)
889                break;
890            else
891                ocsp_uri = NULL;
892        }
893    }
894
895    apr_pool_destroy(tmp);
896    return ocsp_uri;
897}
898
899
900
901/*
902 * Like in the general post_config hook the HTTP status codes for
903 * errors are just for fun. What matters is "neither OK nor DECLINED"
904 * to denote an error.
905 */
906int mgs_ocsp_post_config_server(apr_pool_t *pconf,
907                                apr_pool_t *ptemp __attribute__((unused)),
908                                server_rec *server)
909{
910    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
911        ap_get_module_config(server->module_config, &gnutls_module);
912
913    if (sc->certs_x509_chain_num < 2)
914    {
915        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, server,
916                     "OCSP stapling is enabled but no CA certificate "
917                     "available for %s:%d, make sure it is included in "
918                     "GnuTLSCertificateFile!",
919                     server->server_hostname, server->addrs->host_port);
920        return HTTP_NOT_FOUND;
921    }
922
923    /* set default values for unset parameters */
924    if (sc->ocsp_check_nonce == GNUTLS_ENABLED_UNSET)
925        sc->ocsp_check_nonce = GNUTLS_ENABLED_TRUE;
926    if (sc->ocsp_grace_time == MGS_TIMEOUT_UNSET)
927        sc->ocsp_grace_time = apr_time_from_sec(MGS_OCSP_GRACE_TIME);
928    if (sc->ocsp_failure_timeout == MGS_TIMEOUT_UNSET)
929        sc->ocsp_failure_timeout = apr_time_from_sec(MGS_OCSP_FAILURE_TIMEOUT);
930    if (sc->ocsp_socket_timeout == MGS_TIMEOUT_UNSET)
931        sc->ocsp_socket_timeout = apr_time_from_sec(MGS_OCSP_SOCKET_TIMEOUT);
932
933    sc->ocsp = apr_palloc(pconf, sizeof(struct mgs_ocsp_data));
934
935    sc->ocsp->fingerprint =
936        mgs_get_cert_fingerprint(pconf, sc->certs_x509_crt_chain[0]);
937    if (sc->ocsp->fingerprint.data == NULL)
938        return HTTP_INTERNAL_SERVER_ERROR;
939
940    sc->ocsp->uri = mgs_cert_get_ocsp_uri(pconf,
941                                          sc->certs_x509_crt_chain[0]);
942    if (sc->ocsp->uri == NULL && sc->ocsp_response_file == NULL)
943    {
944        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, server,
945                     "OCSP stapling is enabled for for %s:%d, but there is "
946                     "neither an OCSP URI in the certificate nor a "
947                     "GnuTLSOCSPResponseFile setting for this host!",
948                     server->server_hostname, server->addrs->host_port);
949        return HTTP_NOT_FOUND;
950    }
951
952    sc->ocsp->trust = apr_palloc(pconf,
953                                 sizeof(gnutls_x509_trust_list_t));
954     /* Only the direct issuer may sign the OCSP response or an OCSP
955      * signer. */
956    int ret = mgs_create_ocsp_trust_list(sc->ocsp->trust,
957                                         &(sc->certs_x509_crt_chain[1]),
958                                         1);
959    if (ret != GNUTLS_E_SUCCESS)
960    {
961        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, server,
962                     "Could not create OCSP trust list: %s (%d)",
963                     gnutls_strerror(ret), ret);
964        return HTTP_INTERNAL_SERVER_ERROR;
965    }
966    /* deinit trust list when the config pool is destroyed */
967    apr_pool_cleanup_register(pconf, sc->ocsp->trust,
968                              mgs_cleanup_trust_list,
969                              apr_pool_cleanup_null);
970
971    return OK;
972}
Note: See TracBrowser for help on using the repository browser.