source: mod_gnutls/src/gnutls_ocsp.c @ e932ba5

proxy-ticket
Last change on this file since e932ba5 was e932ba5, checked in by Fiona Klute <fiona.klute@…>, 7 months ago

Do not enforce OCSP nonces by default

The reason for this change is that in practice most public CAs do not
support OCSP nonces, which is permitted by both RFC 6960 and the
CA/Browser Forum baseline requirements. In this situation enforcing
correct nonces by default makes the automatic OCSP stapling support
mostly useless, so I'm changing the default.

  • Property mode set to 100644
File size: 46.6 KB
Line 
1/*
2 *  Copyright 2016-2020 Fiona Klute
3 *
4 *  Licensed under the Apache License, Version 2.0 (the "License");
5 *  you may not use this file except in compliance with the License.
6 *  You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 *  Unless required by applicable law or agreed to in writing, software
11 *  distributed under the License is distributed on an "AS IS" BASIS,
12 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 *  See the License for the specific language governing permissions and
14 *  limitations under the License.
15 */
16
17#include "gnutls_ocsp.h"
18#include "mod_gnutls.h"
19#include "gnutls_cache.h"
20#include "gnutls_config.h"
21#include "gnutls_util.h"
22#include "gnutls_watchdog.h"
23
24#include <apr_escape.h>
25#include <apr_lib.h>
26#include <apr_time.h>
27#include <gnutls/crypto.h>
28#include <gnutls/ocsp.h>
29#include <mod_watchdog.h>
30#include <string.h>
31#include <time.h>
32
33#ifdef APLOG_USE_MODULE
34APLOG_USE_MODULE(gnutls);
35#endif
36
37/** maximum supported OCSP response size, 8K should be plenty */
38#define OCSP_RESP_SIZE_MAX (8 * 1024)
39#define OCSP_REQ_TYPE "application/ocsp-request"
40#define OCSP_RESP_TYPE "application/ocsp-response"
41
42/** Dummy data for failure cache entries (one byte). */
43#define OCSP_FAILURE_CACHE_DATA 0x0f
44/** Macro to check if an OCSP reponse pointer contains a cached
45 * failure */
46#define IS_FAILURE_RESPONSE(resp) \
47    (((resp)->size == sizeof(unsigned char)) &&                     \
48     (*((unsigned char *) (resp)->data) == OCSP_FAILURE_CACHE_DATA))
49
50
51#define _log_one_ocsp_fail(str, srv)                                    \
52    ap_log_error(APLOG_MARK, APLOG_INFO, APR_EGENERAL, (srv),           \
53                 "Reason for failed OCSP response verification: %s", (str))
54/**
55 * Log all matching reasons for verification failure
56 */
57static void _log_verify_fail_reason(const unsigned int verify, server_rec *s)
58{
59    if (verify & GNUTLS_OCSP_VERIFY_SIGNER_NOT_FOUND)
60        _log_one_ocsp_fail("Signer cert not found", s);
61
62    if (verify & GNUTLS_OCSP_VERIFY_SIGNER_KEYUSAGE_ERROR)
63        _log_one_ocsp_fail("Signer cert keyusage error", s);
64
65    if (verify & GNUTLS_OCSP_VERIFY_UNTRUSTED_SIGNER)
66        _log_one_ocsp_fail("Signer cert is not trusted", s);
67
68    if (verify & GNUTLS_OCSP_VERIFY_INSECURE_ALGORITHM)
69        _log_one_ocsp_fail("Insecure algorithm", s);
70
71    if (verify & GNUTLS_OCSP_VERIFY_SIGNATURE_FAILURE)
72        _log_one_ocsp_fail("Signature failure", s);
73
74    if (verify & GNUTLS_OCSP_VERIFY_CERT_NOT_ACTIVATED)
75        _log_one_ocsp_fail("Signer cert not yet activated", s);
76
77    if (verify & GNUTLS_OCSP_VERIFY_CERT_EXPIRED)
78        _log_one_ocsp_fail("Signer cert expired", s);
79}
80
81
82
83const char *mgs_ocsp_stapling_enable(cmd_parms *parms,
84                                     void *dummy __attribute__((unused)),
85                                     const int arg)
86{
87    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
88        ap_get_module_config(parms->server->module_config, &gnutls_module);
89
90    if (arg)
91        sc->ocsp_staple = GNUTLS_ENABLED_TRUE;
92    else
93        sc->ocsp_staple = GNUTLS_ENABLED_FALSE;
94
95    return NULL;
96}
97
98
99
100const char *mgs_set_ocsp_auto_refresh(cmd_parms *parms,
101                                      void *dummy __attribute__((unused)),
102                                      const int arg)
103{
104    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
105        ap_get_module_config(parms->server->module_config, &gnutls_module);
106
107    if (arg)
108        sc->ocsp_auto_refresh = GNUTLS_ENABLED_TRUE;
109    else
110        sc->ocsp_auto_refresh = GNUTLS_ENABLED_FALSE;
111
112    return NULL;
113}
114
115
116
117const char *mgs_set_ocsp_check_nonce(cmd_parms *parms,
118                                     void *dummy __attribute__((unused)),
119                                     const int arg)
120{
121    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
122        ap_get_module_config(parms->server->module_config, &gnutls_module);
123
124    if (arg)
125        sc->ocsp_check_nonce = GNUTLS_ENABLED_TRUE;
126    else
127        sc->ocsp_check_nonce = GNUTLS_ENABLED_FALSE;
128
129    return NULL;
130}
131
132
133
134const char *mgs_store_ocsp_response_path(cmd_parms *parms,
135                                         void *dummy __attribute__((unused)),
136                                         int argc, char *const *argv)
137{
138    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
139        ap_get_module_config(parms->server->module_config, &gnutls_module);
140
141    sc->ocsp_response_file_num = argc;
142    sc->ocsp_response_file = apr_palloc(parms->pool, sizeof(char *) * argc);
143    for (int i = 0; i < argc; i++)
144    {
145        if (strcmp(argv[i], "") == 0)
146            sc->ocsp_response_file[i] = NULL;
147        else
148            sc->ocsp_response_file[i] =
149                ap_server_root_relative(parms->pool, argv[i]);
150    }
151    return NULL;
152}
153
154
155
156/**
157 * Create an OCSP request for the certificate of the given server. The
158 * DER encoded request is stored in 'req' (must be released with
159 * gnutls_free() when no longer needed), its nonce in 'nonce' (same,
160 * if not NULL).
161 *
162 * @param s server reference for logging
163 *
164 * @return GNUTLS_E_SUCCESS, or a GnuTLS error code.
165 */
166static int mgs_create_ocsp_request(server_rec *s,
167                                   mgs_ocsp_data_t req_data,
168                                   gnutls_datum_t *req,
169                                   gnutls_datum_t *nonce)
170    __attribute__((nonnull(1, 3)));
171static int mgs_create_ocsp_request(server_rec *s,
172                                   mgs_ocsp_data_t req_data,
173                                   gnutls_datum_t *req,
174                                   gnutls_datum_t *nonce)
175{
176    gnutls_ocsp_req_t r;
177    int ret = gnutls_ocsp_req_init(&r);
178    if (ret != GNUTLS_E_SUCCESS)
179    {
180        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
181                     "Could not initialize OCSP request structure: %s (%d)",
182                     gnutls_strerror(ret), ret);
183        return ret;
184    }
185
186    /* issuer is set to a reference, so musn't be cleaned up */
187    gnutls_x509_crt_t issuer;
188    ret = gnutls_x509_trust_list_get_issuer(*req_data->trust, req_data->cert,
189                                            &issuer, 0);
190    if (ret != GNUTLS_E_SUCCESS)
191    {
192        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
193                     "Could not get issuer from trust list: %s (%d)",
194                     gnutls_strerror(ret), ret);
195        gnutls_ocsp_req_deinit(r);
196        return ret;
197    }
198
199    /* GnuTLS doc says that the digest is "normally"
200     * GNUTLS_DIG_SHA1. */
201    ret = gnutls_ocsp_req_add_cert(r, GNUTLS_DIG_SHA256,
202                                   issuer, req_data->cert);
203
204    if (ret != GNUTLS_E_SUCCESS)
205    {
206        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
207                     "Adding certificate to OCSP request for %s:%d "
208                     "failed: %s (%d)",
209                     s->server_hostname, s->addrs->host_port,
210                     gnutls_strerror(ret), ret);
211        gnutls_ocsp_req_deinit(r);
212        return ret;
213    }
214
215    ret = gnutls_ocsp_req_randomize_nonce(r);
216    if (ret != GNUTLS_E_SUCCESS)
217    {
218        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
219                     "OCSP nonce creation failed: %s (%d)",
220                     gnutls_strerror(ret), ret);
221        gnutls_ocsp_req_deinit(r);
222        return ret;
223    }
224
225    if (nonce != NULL)
226    {
227        ret = gnutls_ocsp_req_get_nonce(r, NULL, nonce);
228        if (ret != GNUTLS_E_SUCCESS)
229        {
230            ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
231                         "Could not get nonce: %s (%d)",
232                         gnutls_strerror(ret), ret);
233            gnutls_free(nonce->data);
234            nonce->data = NULL;
235            nonce->size = 0;
236            gnutls_ocsp_req_deinit(r);
237            return ret;
238        }
239    }
240
241    ret = gnutls_ocsp_req_export(r, req);
242    if (ret != GNUTLS_E_SUCCESS)
243    {
244        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
245                     "OCSP request export failed: %s (%d)",
246                     gnutls_strerror(ret), ret);
247        gnutls_free(req->data);
248        req->data = NULL;
249        req->size = 0;
250        if (nonce != NULL)
251        {
252            gnutls_free(nonce->data);
253            nonce->data = NULL;
254            nonce->size = 0;
255        }
256        gnutls_ocsp_req_deinit(r);
257        return ret;
258    }
259
260    gnutls_ocsp_req_deinit(r);
261    return ret;
262}
263
264
265
266/**
267 * Check if the provided OCSP response is usable for stapling in
268 * connections to this server. Returns GNUTLS_E_SUCCESS if yes.
269 *
270 * Supports only one certificate status per response.
271 *
272 * If expiry is not NULL, it will be set to the nextUpdate time
273 * contained in the response, or zero if the response does not contain
274 * a nextUpdate field.
275 *
276 * If nonce is not NULL, the response must contain a matching nonce.
277 */
278int check_ocsp_response(server_rec *s, mgs_ocsp_data_t req_data,
279                        const gnutls_datum_t *ocsp_response,
280                        apr_time_t* expiry, const gnutls_datum_t *nonce)
281    __attribute__((nonnull(1, 3)));
282int check_ocsp_response(server_rec *s, mgs_ocsp_data_t req_data,
283                        const gnutls_datum_t *ocsp_response,
284                        apr_time_t* expiry, const gnutls_datum_t *nonce)
285{
286    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
287        ap_get_module_config(s->module_config, &gnutls_module);
288
289    if (req_data->trust == NULL)
290    {
291        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
292                     "No OCSP trust list available for server \"%s\"!",
293                     s->server_hostname);
294        return GNUTLS_E_NO_CERTIFICATE_FOUND;
295    }
296
297    gnutls_ocsp_resp_t resp;
298    int ret = gnutls_ocsp_resp_init(&resp);
299    if (ret != GNUTLS_E_SUCCESS)
300    {
301        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
302                     "Could not initialize OCSP response structure: %s (%d)",
303                     gnutls_strerror(ret), ret);
304        goto resp_cleanup;
305    }
306    ret = gnutls_ocsp_resp_import(resp, ocsp_response);
307    if (ret != GNUTLS_E_SUCCESS)
308    {
309        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
310                     "Importing OCSP response failed: %s (%d)",
311                     gnutls_strerror(ret), ret);
312        goto resp_cleanup;
313    }
314
315    ret = gnutls_ocsp_resp_check_crt(resp, 0, req_data->cert);
316    if (ret != GNUTLS_E_SUCCESS)
317    {
318        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
319                     "OCSP response is not for server certificate: %s (%d)",
320                     gnutls_strerror(ret), ret);
321        goto resp_cleanup;
322    }
323
324    unsigned int verify;
325    ret = gnutls_ocsp_resp_verify(resp, *(req_data->trust), &verify, 0);
326    if (ret != GNUTLS_E_SUCCESS)
327    {
328        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
329                     "OCSP response verification failed: %s (%d)",
330                     gnutls_strerror(ret), ret);
331        goto resp_cleanup;
332    }
333    else
334    {
335        /* verification worked, check the result */
336        if (verify != 0)
337        {
338            _log_verify_fail_reason(verify, s);
339            ret = GNUTLS_E_OCSP_RESPONSE_ERROR;
340            goto resp_cleanup;
341        }
342        else
343            ap_log_error(APLOG_MARK, APLOG_TRACE1, APR_SUCCESS, s,
344                         "OCSP response signature is valid.");
345    }
346
347    /* Even some large CAs do not support nonces, probably because
348     * that way they can cache responses. :-/ */
349    if (nonce != NULL && sc->ocsp_check_nonce)
350    {
351        gnutls_datum_t resp_nonce;
352        ret = gnutls_ocsp_resp_get_nonce(resp, 0, &resp_nonce);
353        if (ret != GNUTLS_E_SUCCESS)
354        {
355            ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
356                         "Could not get OCSP response nonce: %s (%d)",
357                         gnutls_strerror(ret), ret);
358            goto resp_cleanup;
359        }
360        if (resp_nonce.size != nonce->size
361            || memcmp(resp_nonce.data, nonce->data, nonce->size))
362        {
363            ret = GNUTLS_E_OCSP_RESPONSE_ERROR;
364            ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
365                         "OCSP response invalid: nonce mismatch");
366            gnutls_free(resp_nonce.data);
367            goto resp_cleanup;
368        }
369        ap_log_error(APLOG_MARK, APLOG_TRACE2, APR_SUCCESS, s,
370                     "OCSP response: nonce match");
371        gnutls_free(resp_nonce.data);
372    }
373
374    /* OK, response is for our certificate and valid, let's get the
375     * actual response data. */
376    unsigned int cert_status;
377    time_t this_update;
378    time_t next_update;
379    ret = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL, NULL,
380                                      &cert_status, &this_update,
381                                      &next_update, NULL, NULL);
382    if (ret != GNUTLS_E_SUCCESS)
383    {
384        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
385                     "Could not get OCSP response data: %s (%d)",
386                     gnutls_strerror(ret), ret);
387        goto resp_cleanup;
388    }
389
390    apr_time_t now = apr_time_now();
391    apr_time_t valid_at;
392    apr_time_ansi_put(&valid_at, this_update);
393    /* Buffer for human-readable times produced by apr_rfc822_date,
394     * see apr_time.h */
395    char date_str[APR_RFC822_DATE_LEN];
396    apr_rfc822_date(date_str, valid_at);
397
398    if (now < valid_at)
399    {
400        /* We don't know if our clock or that of the OCSP responder is
401         * out of sync, so warn but continue. */
402        ap_log_error(APLOG_MARK, APLOG_WARNING, APR_EGENERAL, s,
403                     "OSCP response claims to be from future (%s), check "
404                     "time synchronization!", date_str);
405    }
406
407    if (next_update == (time_t) -1)
408    {
409        ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, s,
410                     "OSCP response does not contain nextUpdate info.");
411        if (expiry != NULL)
412            *expiry = 0;
413    }
414    else
415    {
416        apr_time_t valid_to;
417        apr_time_ansi_put(&valid_to, next_update);
418        if (expiry != NULL)
419            *expiry = valid_to;
420        if (now > valid_to)
421        {
422            apr_rfc822_date(date_str, valid_to);
423            ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
424                         "OCSP response has expired at %s!", date_str);
425            /* Do not send a stale response */
426            ret = GNUTLS_E_OCSP_RESPONSE_ERROR;
427            goto resp_cleanup;
428        }
429    }
430
431    /* What's the actual status? Will be one of
432     * gnutls_ocsp_cert_status_t as defined in gnutls/ocsp.h. */
433    if (cert_status == GNUTLS_OCSP_CERT_GOOD)
434    {
435        /* Yay, everything's good! */
436        ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, s,
437                     "CA flagged certificate as valid at %s.", date_str);
438    }
439    else
440    {
441        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
442                     "CA flagged certificate as %s at %s.",
443                     cert_status == GNUTLS_OCSP_CERT_REVOKED ?
444                     "revoked" : "unknown", date_str);
445        ret = GNUTLS_E_OCSP_RESPONSE_ERROR;
446    }
447
448 resp_cleanup:
449    gnutls_ocsp_resp_deinit(resp);
450    return ret;
451}
452
453
454
455/*
456 * Returns the certificate fingerprint, memory is allocated from p.
457 */
458static gnutls_datum_t mgs_get_cert_fingerprint(apr_pool_t *p,
459                                               gnutls_x509_crt_t cert)
460{
461    gnutls_datum_t fingerprint = {NULL, 0};
462    size_t fplen = 0;
463    gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, NULL, &fplen);
464    unsigned char * fp = apr_palloc(p, fplen);
465    gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, fp, &fplen);
466    /* Safe integer type conversion: The types of fingerprint.size
467     * (unsigned int) and fplen (size_t) may have different
468     * lengths. */
469#if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__)
470    if (__builtin_expect(fplen <= UINT_MAX, 1))
471    {
472        fingerprint.size = (unsigned int) fplen;
473        fingerprint.data = fp;
474    }
475#else
476    if (__builtin_add_overflow(fplen, 0, &fingerprint.size))
477        fingerprint.size = 0;
478    else
479        fingerprint.data = fp;
480#endif
481    return fingerprint;
482}
483
484
485
486static apr_status_t do_ocsp_request(apr_pool_t *p, server_rec *s,
487                                    apr_uri_t *uri,
488                                    gnutls_datum_t *request,
489                                    gnutls_datum_t *response)
490    __attribute__((nonnull));
491static apr_status_t do_ocsp_request(apr_pool_t *p, server_rec *s,
492                                    apr_uri_t *uri,
493                                    gnutls_datum_t *request,
494                                    gnutls_datum_t *response)
495{
496    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
497        ap_get_module_config(s->module_config, &gnutls_module);
498
499    if (apr_strnatcmp(uri->scheme, "http"))
500    {
501        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
502                     "Scheme \"%s\" is not supported for OCSP requests!",
503                     uri->scheme);
504        return APR_EINVAL;
505    }
506
507    const char* header = http_post_header(p, uri,
508                                          OCSP_REQ_TYPE, OCSP_RESP_TYPE,
509                                          request->size);
510    ap_log_error(APLOG_MARK, APLOG_TRACE2, APR_SUCCESS, s,
511                 "OCSP POST header: %s", header);
512
513    /* Find correct port */
514    apr_port_t port = uri->port ?
515        uri->port : apr_uri_port_of_scheme(uri->scheme);
516
517    apr_sockaddr_t *sa;
518    apr_status_t rv = apr_sockaddr_info_get(&sa, uri->hostname,
519                                            APR_UNSPEC, port, 0, p);
520    if (rv != APR_SUCCESS)
521    {
522        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
523                     "Address resolution for OCSP responder %s failed.",
524                     uri->hostinfo);
525    }
526
527    /* There may be multiple answers, try them in order until one
528     * works. */
529    apr_socket_t *sock;
530    while (sa)
531    {
532        rv = apr_socket_create(&sock, sa->family, SOCK_STREAM,
533                               APR_PROTO_TCP, p);
534        if (rv == APR_SUCCESS)
535        {
536            apr_socket_timeout_set(sock, sc->ocsp_socket_timeout);
537            rv = apr_socket_connect(sock, sa);
538            if (rv == APR_SUCCESS)
539                /* Connected! */
540                break;
541            apr_socket_close(sock);
542        }
543        sa = sa->next;
544    }
545    /* If the socket is connected, 'sa' points at the matching
546     * address. */
547    if (sa == NULL)
548    {
549        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
550                     "Connecting to OCSP responder %s failed.",
551                     uri->hostinfo);
552        return rv;
553    }
554
555    /* Header is generated locally, so strlen() is safe. */
556    rv = sock_send_buf(sock, header, strlen(header));
557    if (rv == APR_SUCCESS)
558        rv = sock_send_buf(sock, (char*) request->data, request->size);
559    /* catches errors from both header and request */
560    if (rv != APR_SUCCESS)
561    {
562        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
563                     "Sending OCSP request failed.");
564        goto exit;
565    }
566
567    /* Prepare bucket brigades to read the response header. BBs make
568     * it easy to split the header into lines. */
569    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
570    apr_bucket_brigade *bb = apr_brigade_create(p, ba);
571    /* will carry split response headers */
572    apr_bucket_brigade *rh = apr_brigade_create(p, ba);
573
574    APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_socket_create(sock, ba));
575    /* The first line in the response header must be the status, check
576     * for OK status code. Line looks similar to "HTTP/1.0 200 OK". */
577    const char *h = read_line(p, bb, rh);
578    const char *code = 0;
579    if (h == NULL
580        || strncmp(h, "HTTP/", 5)
581        || (code = ap_strchr(h, ' ')) == NULL
582        || apr_atoi64(code + 1) != HTTP_OK)
583    {
584        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
585                     "Invalid HTTP response status from %s: %s",
586                     uri->hostinfo, h);
587        rv = APR_ECONNRESET;
588        goto exit;
589    }
590    /* Read remaining header lines */
591    for (h = read_line(p, bb, rh); h != NULL && apr_strnatcmp(h, "") != 0;
592         h = read_line(p, bb, rh))
593    {
594        ap_log_error(APLOG_MARK, APLOG_TRACE2, APR_SUCCESS, s,
595                     "Received header: %s", h);
596    }
597    /* The last header line should be empty (""), NULL indicates an
598     * error. */
599    if (h == NULL)
600    {
601        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
602                     "Error while reading HTTP response header from %s",
603                     uri->hostinfo);
604        rv = APR_ECONNRESET;
605        goto exit;
606    }
607
608    /* Headers have been consumed, the rest of the available data
609     * should be the actual response. */
610    apr_size_t len = OCSP_RESP_SIZE_MAX;
611    char buf[OCSP_RESP_SIZE_MAX];
612    /* apr_brigade_pflatten() can allocate directly from the pool, but
613     * the documentation does not describe a way to limit the size of
614     * the buffer, which is necessary here to prevent DoS by endless
615     * response. Use apr_brigade_flatten() to read to a stack pool,
616     * then create a copy to return. */
617    rv = apr_brigade_flatten(bb, buf, &len);
618    if (rv != APR_SUCCESS)
619    {
620        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
621                     "Failed to read OCSP response.");
622        goto exit;
623    }
624
625    /* With the length restriction this really should not overflow. */
626#if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__)
627    if (__builtin_expect(len > UINT_MAX, 0))
628#else
629    if (__builtin_add_overflow(len, 0, &response->size))
630#endif
631    {
632        response->data = NULL;
633        rv = APR_ENOMEM;
634    }
635    else
636    {
637#if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__)
638        response->size = (unsigned int) len;
639#endif
640        response->data = apr_pmemdup(p, buf, len);
641    }
642
643 exit:
644    apr_socket_close(sock);
645    return rv;
646}
647
648
649
650/**
651 * Get a fresh OCSP response and put it into the cache.
652 *
653 * @param s server that needs a new response
654 *
655 * @param req_data struct describing the certificate for which to
656 * cache a response
657 *
658 * @param cache_expiry If not `NULL`, this `apr_time_t` will be set to
659 * the expiration time of the cache entry. Remains unchanged on
660 * failure.
661 *
662 * @return APR_SUCCESS or an APR error code
663 */
664static apr_status_t mgs_cache_ocsp_response(server_rec *s,
665                                            mgs_ocsp_data_t req_data,
666                                            apr_time_t *cache_expiry)
667{
668    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
669        ap_get_module_config(s->module_config, &gnutls_module);
670
671    if (sc->ocsp_cache == NULL)
672    {
673        /* OCSP caching requires a cache. */
674        return APR_ENOTIMPL;
675    }
676
677    apr_pool_t *tmp;
678    apr_status_t rv = apr_pool_create(&tmp, NULL);
679    if (rv != APR_SUCCESS)
680    {
681        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
682                     "could not create temporary pool for %s",
683                     __func__);
684        return rv;
685    }
686
687    gnutls_datum_t resp;
688    gnutls_datum_t nonce = { NULL, 0 };
689
690    if (req_data->response_file != NULL)
691    {
692        ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, s,
693                     "Loading OCSP response from %s",
694                     req_data->response_file);
695        rv = datum_from_file(tmp, req_data->response_file, &resp);
696        if (rv != APR_SUCCESS)
697        {
698            ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
699                         "Loading OCSP response from %s failed!",
700                         req_data->response_file);
701            apr_pool_destroy(tmp);
702            return rv;
703        }
704    }
705    else
706    {
707        gnutls_datum_t req;
708        int ret = mgs_create_ocsp_request(s, req_data, &req, &nonce);
709        if (ret == GNUTLS_E_SUCCESS)
710        {
711            ap_log_error(APLOG_MARK, APLOG_TRACE2, APR_SUCCESS, s,
712                         "created OCSP request for %s:%d: %s",
713                         s->server_hostname, s->addrs->host_port,
714                         apr_pescape_hex(tmp, req.data, req.size, 0));
715        }
716        else
717        {
718            gnutls_free(req.data);
719            gnutls_free(nonce.data);
720            apr_pool_destroy(tmp);
721            return APR_EGENERAL;
722        }
723
724        rv = do_ocsp_request(tmp, s, req_data->uri, &req, &resp);
725        gnutls_free(req.data);
726        if (rv != APR_SUCCESS)
727        {
728            /* do_ocsp_request() does its own error logging. */
729            gnutls_free(nonce.data);
730            apr_pool_destroy(tmp);
731            return rv;
732        }
733    }
734
735    apr_time_t next_update;
736    if (check_ocsp_response(s, req_data, &resp, &next_update,
737                            nonce.size ? &nonce : NULL)
738        != GNUTLS_E_SUCCESS)
739    {
740        ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_EGENERAL, s,
741                     "OCSP response validation failed, cannot "
742                     "update cache.");
743        apr_pool_destroy(tmp);
744        gnutls_free(nonce.data);
745        return APR_EGENERAL;
746    }
747    gnutls_free(nonce.data);
748
749    apr_time_t expiry = apr_time_now() + sc->ocsp_cache_time;
750    /* Make sure that a response is not cached beyond its nextUpdate
751     * time. If the variable next_update is zero, the response does
752     * not contain a nextUpdate field. */
753    if (next_update != 0 && next_update < expiry)
754    {
755        char date_str[APR_RFC822_DATE_LEN];
756        apr_rfc822_date(date_str, next_update);
757        ap_log_error(APLOG_MARK, APLOG_WARNING, APR_EGENERAL, s,
758                     "OCSP response timeout restricted to nextUpdate time %s. "
759                     "Check if GnuTLSOCSPCacheTimeout is appropriate.",
760                     date_str);
761        expiry = next_update;
762    }
763
764    int r = mgs_cache_store(sc->ocsp_cache, s,
765                            req_data->fingerprint, resp, expiry);
766    /* destroy pool, and original copy of the OCSP response with it */
767    apr_pool_destroy(tmp);
768    if (r != 0)
769    {
770        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
771                      "Storing OCSP response in cache failed.");
772        return APR_EGENERAL;
773    }
774
775    if (cache_expiry != NULL)
776        *cache_expiry = expiry;
777    return APR_SUCCESS;
778}
779
780
781
782/**
783 * Retries after failed OCSP requests must be rate limited. If the
784 * responder is overloaded or buggy we don't want to add too much more
785 * load, and if a MITM is messing with requests a repetition loop
786 * might end up being a self-inflicted denial of service. This
787 * function writes a specially formed entry to the cache to indicate a
788 * recent failure.
789 *
790 * @param s the server for which an OCSP request failed
791 *
792 * @param req_data OCSP data structure for the certificate that could
793 * not be checked
794 *
795 * @param timeout lifetime of the cache entry
796 */
797static void mgs_cache_ocsp_failure(server_rec *s,
798                                   mgs_ocsp_data_t req_data,
799                                   apr_interval_time_t timeout)
800{
801    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
802        ap_get_module_config(s->module_config, &gnutls_module);
803
804    unsigned char c = OCSP_FAILURE_CACHE_DATA;
805    gnutls_datum_t dummy = {
806        .data = &c,
807        .size = sizeof(c)
808    };
809    apr_time_t expiry = apr_time_now() + timeout;
810
811    int r = mgs_cache_store(sc->ocsp_cache, s,
812                            req_data->fingerprint, dummy, expiry);
813    if (r != 0)
814        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
815                     "Caching OCSP failure failed.");
816}
817
818
819
820int mgs_get_ocsp_response(mgs_handle_t *ctxt,
821                          mgs_ocsp_data_t req_data,
822                          gnutls_datum_t *ocsp_response)
823{
824    mgs_srvconf_rec *sc = ctxt->sc;
825
826    if (!sc->ocsp_staple || sc->ocsp_cache == NULL)
827    {
828        /* OCSP must be enabled and caching requires a cache. */
829        return GNUTLS_E_NO_CERTIFICATE_STATUS;
830    }
831
832    // TODO: Large allocation, and the pool system doesn't offer realloc
833    ocsp_response->data = apr_palloc(ctxt->c->pool, OCSP_RESP_SIZE_MAX);
834    ocsp_response->size = OCSP_RESP_SIZE_MAX;
835
836    apr_status_t rv = mgs_cache_fetch(sc->ocsp_cache,
837                                      ctxt->c->base_server,
838                                      req_data->fingerprint,
839                                      ocsp_response,
840                                      ctxt->c->pool);
841    if (rv != APR_SUCCESS)
842    {
843        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, APR_EGENERAL, ctxt->c,
844                      "Fetching OCSP response from cache failed.");
845    }
846    else if (IS_FAILURE_RESPONSE(ocsp_response))
847    {
848        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_EGENERAL, ctxt->c,
849                      "Cached OCSP failure found for %s.",
850                      ctxt->c->base_server->server_hostname);
851        goto fail_cleanup;
852    }
853    else
854    {
855        return GNUTLS_E_SUCCESS;
856    }
857    /* keep response buffer, reset size for reuse */
858    ocsp_response->size = OCSP_RESP_SIZE_MAX;
859
860    /* If the cache had no response or an invalid one, try to update. */
861    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ctxt->c,
862                  "No valid OCSP response in cache, trying to update.");
863
864    rv = apr_global_mutex_trylock(sc->ocsp_mutex);
865    if (APR_STATUS_IS_EBUSY(rv))
866    {
867        /* Another thread is currently holding the mutex, wait. */
868        apr_global_mutex_lock(sc->ocsp_mutex);
869        /* Check if this other thread updated the response we need. It
870         * would be better to have a vhost specific mutex, but at the
871         * moment there's no good way to integrate that with the
872         * Apache Mutex directive. */
873        rv = mgs_cache_fetch(sc->ocsp_cache,
874                             ctxt->c->base_server,
875                             req_data->fingerprint,
876                             ocsp_response,
877                             ctxt->c->pool);
878        if (rv == APR_SUCCESS)
879        {
880            apr_global_mutex_unlock(sc->ocsp_mutex);
881            /* Check if the response is valid. */
882            if (IS_FAILURE_RESPONSE(ocsp_response))
883            {
884                ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_EGENERAL, ctxt->c,
885                              "Cached OCSP failure found for %s.",
886                              ctxt->c->base_server->server_hostname);
887                goto fail_cleanup;
888            }
889            else
890                return GNUTLS_E_SUCCESS;
891        }
892        else
893        {
894            /* keep response buffer, reset size for reuse */
895            ocsp_response->size = OCSP_RESP_SIZE_MAX;
896        }
897    }
898
899    rv = mgs_cache_ocsp_response(ctxt->c->base_server, req_data, NULL);
900    if (rv != APR_SUCCESS)
901    {
902        ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, ctxt->c,
903                      "Caching a fresh OCSP response failed");
904        /* cache failure to rate limit retries */
905        mgs_cache_ocsp_failure(ctxt->c->base_server,
906                               req_data,
907                               sc->ocsp_failure_timeout);
908        apr_global_mutex_unlock(sc->ocsp_mutex);
909        goto fail_cleanup;
910    }
911    apr_global_mutex_unlock(sc->ocsp_mutex);
912
913    /* retry reading from cache */
914    rv = mgs_cache_fetch(sc->ocsp_cache,
915                         ctxt->c->base_server,
916                         req_data->fingerprint,
917                         ocsp_response,
918                         ctxt->c->pool);
919    if (rv != APR_SUCCESS)
920    {
921        ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c,
922                      "Fetching OCSP response from cache failed on retry.");
923    }
924    else
925    {
926        return GNUTLS_E_SUCCESS;
927    }
928
929    /* failure, reset struct, buffer will be released with the
930     * connection pool */
931 fail_cleanup:
932    ocsp_response->size = 0;
933    ocsp_response->data = NULL;
934    return GNUTLS_E_NO_CERTIFICATE_STATUS;
935}
936
937
938
939int mgs_create_ocsp_trust_list(gnutls_x509_trust_list_t *tl,
940                               const gnutls_x509_crt_t *chain,
941                               const int num)
942{
943    int added = 0;
944    int ret = gnutls_x509_trust_list_init(tl, num);
945
946    if (ret == GNUTLS_E_SUCCESS)
947        added = gnutls_x509_trust_list_add_cas(*tl, chain, num, 0);
948
949    if (added != num)
950        ret = GNUTLS_E_CERTIFICATE_ERROR;
951
952    /* Clean up trust list in case of error */
953    if (ret != GNUTLS_E_SUCCESS)
954        gnutls_x509_trust_list_deinit(*tl, 0);
955
956    return ret;
957}
958
959
960
961apr_status_t mgs_cleanup_trust_list(void *data)
962{
963    gnutls_x509_trust_list_t *tl = (gnutls_x509_trust_list_t *) data;
964    gnutls_x509_trust_list_deinit(*tl, 0);
965    return APR_SUCCESS;
966}
967
968
969
970apr_uri_t * mgs_cert_get_ocsp_uri(apr_pool_t *p, gnutls_x509_crt_t cert)
971{
972    apr_pool_t *tmp;
973    apr_status_t rv = apr_pool_create(&tmp, p);
974    if (rv != APR_SUCCESS)
975        return NULL;
976
977    apr_uri_t *ocsp_uri = NULL;
978
979    int ret = GNUTLS_E_SUCCESS;
980    /* search authority info access for OCSP URI */
981    for (int seq = 0; ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; seq++)
982    {
983        gnutls_datum_t ocsp_access_data;
984        ret = gnutls_x509_crt_get_authority_info_access(cert, seq,
985                                                        GNUTLS_IA_OCSP_URI,
986                                                        &ocsp_access_data,
987                                                        NULL);
988        if (ret == GNUTLS_E_SUCCESS)
989        {
990            /* create NULL terminated string */
991            char *ocsp_str =
992                apr_pstrndup(tmp, (const char*) ocsp_access_data.data,
993                             ocsp_access_data.size);
994            gnutls_free(ocsp_access_data.data);
995
996            ocsp_uri = apr_palloc(p, sizeof(apr_uri_t));
997            rv = apr_uri_parse(p, ocsp_str, ocsp_uri);
998            if (rv == APR_SUCCESS)
999                break;
1000            else
1001                ocsp_uri = NULL;
1002        }
1003    }
1004
1005    apr_pool_destroy(tmp);
1006    return ocsp_uri;
1007}
1008
1009
1010
1011/** The maximum random fuzz base (half the maximum fuzz) that will not
1012 * overflow. The permitted values are limited to whatever will not
1013 * make an `apr_interval_time_t` variable overflow when multiplied
1014 * with `APR_UINT16_MAX`. With apr_interval_time_t being a 64 bit
1015 * signed integer the maximum fuzz interval is about 4.5 years, which
1016 * should be more than plenty. */
1017#define MAX_FUZZ_BASE (APR_INT64_MAX / APR_UINT16_MAX)
1018
1019/**
1020 * Perform an asynchronous OCSP cache update. This is a callback for
1021 * mod_watchdog, so the API is fixed (except the meaning of data).
1022 *
1023 * @param state watchdog state (starting/running/stopping)
1024 * @param data callback data, contains the server_rec
1025 * @param pool temporary callback pool destroyed after the call
1026 * @return always `APR_SUCCESS` as required by the mod_watchdog API to
1027 * indicate that the callback should be called again
1028 */
1029static apr_status_t mgs_async_ocsp_update(int state,
1030                                          void *data,
1031                                          apr_pool_t *pool)
1032{
1033    /* If the server is stopping there's no need to do an OCSP
1034     * update. */
1035    if (state == AP_WATCHDOG_STATE_STOPPING)
1036        return APR_SUCCESS;
1037
1038    mgs_ocsp_data_t ocsp_data = (mgs_ocsp_data_t) data;
1039    server_rec *server = (server_rec *) ocsp_data->server;
1040    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
1041        ap_get_module_config(server->module_config, &gnutls_module);
1042    apr_time_t expiry = 0;
1043
1044    /* Holding the mutex should help avoiding simultaneous synchronous
1045     * and asynchronous OCSP requests in some edge cases: during
1046     * startup if there's an early request, and if OCSP requests fail
1047     * repeatedly until the cached response expires and a synchronous
1048     * update is triggered before a failure cache entry is
1049     * created. Usually there should be a good OCSP response in the
1050     * cache and the mutex is never touched in
1051     * mgs_get_ocsp_response. */
1052    apr_global_mutex_lock(sc->ocsp_mutex);
1053    apr_status_t rv = mgs_cache_ocsp_response(server, ocsp_data, &expiry);
1054
1055    apr_interval_time_t next_interval;
1056    if (rv != APR_SUCCESS)
1057        next_interval = sc->ocsp_failure_timeout;
1058    else
1059    {
1060        apr_uint16_t random_bytes;
1061        int res = gnutls_rnd(GNUTLS_RND_NONCE, &random_bytes,
1062                             sizeof(random_bytes));
1063        if (__builtin_expect(res < 0, 0))
1064        {
1065            /* Shouldn't ever happen, because a working random number
1066             * generator is required for establishing TLS sessions. */
1067            random_bytes = (apr_uint16_t) apr_time_now();
1068            ap_log_error(APLOG_MARK, APLOG_WARNING, APR_EGENERAL, server,
1069                         "Error getting random number for fuzzy update "
1070                         "interval: %s Falling back on truncated time.",
1071                         gnutls_strerror(res));
1072        }
1073
1074        /* Choose the fuzz interval for the next update between
1075         * `sc->ocsp_fuzz_time` and twice that. */
1076        apr_interval_time_t fuzz = sc->ocsp_fuzz_time
1077            + (sc->ocsp_fuzz_time * random_bytes / APR_UINT16_MAX);
1078
1079        /* With an extremly short timeout or weird nextUpdate value
1080         * next_interval <= 0 might happen. Use the failure timeout to
1081         * avoid endlessly repeating updates. */
1082        next_interval = expiry - apr_time_now();
1083        if (next_interval <= 0)
1084        {
1085            next_interval = sc->ocsp_failure_timeout;
1086            ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, server,
1087                         "OCSP cache expiration time of the response for "
1088                         "%s:%d is in the past, repeating after failure "
1089                         "timeout (GnuTLSOCSPFailureTimeout).",
1090                         server->server_hostname, server->addrs->host_port);
1091        }
1092
1093        /* It's possible to compare maximum fuzz and configured OCSP
1094         * cache timeout at configuration time, but the interval until
1095         * the nextUpdate value expires (or the failure timeout
1096         * fallback above) might be shorter. Make sure that we don't
1097         * end up with a negative interval. */
1098        while (fuzz > next_interval)
1099            fuzz /= 2;
1100        next_interval -= fuzz;
1101    }
1102
1103    sc->singleton_wd->set_callback_interval(sc->singleton_wd->wd,
1104                                            next_interval,
1105                                            ocsp_data, mgs_async_ocsp_update);
1106
1107    ap_log_error(APLOG_MARK, rv == APR_SUCCESS ? APLOG_DEBUG : APLOG_WARNING,
1108                 rv, server,
1109                 "Async OCSP update %s for %s:%d, next update in "
1110                 "%" APR_TIME_T_FMT " seconds.",
1111                 rv == APR_SUCCESS ? "done" : "failed",
1112                 server->server_hostname, server->addrs->host_port,
1113                 apr_time_sec(next_interval));
1114
1115    /* Check if there's still a response in the cache. If not, add a
1116     * failure entry. If there already is a failure entry, refresh
1117     * it. The lifetime of such entries is twice the error timeout to
1118     * make sure they do not expire before the next scheduled
1119     * update. */
1120    if (rv != APR_SUCCESS)
1121    {
1122        gnutls_datum_t ocsp_response;
1123        ocsp_response.data = apr_palloc(pool, OCSP_RESP_SIZE_MAX);
1124        ocsp_response.size = OCSP_RESP_SIZE_MAX;
1125
1126        apr_status_t rv = mgs_cache_fetch(sc->ocsp_cache, server,
1127                                          ocsp_data->fingerprint,
1128                                          &ocsp_response,
1129                                          pool);
1130
1131        if (rv != APR_SUCCESS || (IS_FAILURE_RESPONSE(&ocsp_response)))
1132        {
1133            ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, server,
1134                         "Caching OCSP request failure for %s:%d.",
1135                         server->server_hostname, server->addrs->host_port);
1136            mgs_cache_ocsp_failure(server, ocsp_data,
1137                                   sc->ocsp_failure_timeout * 2);
1138        }
1139    }
1140    apr_global_mutex_unlock(sc->ocsp_mutex);
1141
1142    return APR_SUCCESS;
1143}
1144
1145
1146
1147static const char* configure_cert_staple(mgs_ocsp_data_t ocsp,
1148                                         server_rec *server,
1149                                         mgs_srvconf_rec *sc,
1150                                         int idx,
1151                                         apr_pool_t *pconf)
1152{
1153    ocsp->cert = sc->certs_x509_crt_chain[idx];
1154    ocsp->server = server;
1155
1156    if (sc->ocsp_response_file != NULL && idx < sc->ocsp_response_file_num)
1157        ocsp->response_file = sc->ocsp_response_file[idx];
1158    else
1159        ocsp->response_file = NULL;
1160
1161    ocsp->uri = mgs_cert_get_ocsp_uri(pconf, ocsp->cert);
1162    if (ocsp->uri == NULL && ocsp->response_file == NULL)
1163        return "No OCSP URI in the certificate nor a "
1164            "GnuTLSOCSPResponseFile setting, cannot configure "
1165            "OCSP stapling.";
1166
1167    ocsp->fingerprint =
1168        mgs_get_cert_fingerprint(pconf, sc->certs_x509_crt_chain[idx]);
1169    if (ocsp->fingerprint.data == NULL)
1170        return "Could not read fingerprint from certificate!";
1171
1172    ocsp->trust = apr_palloc(pconf,
1173                             sizeof(gnutls_x509_trust_list_t));
1174    /* Only the direct issuer may sign the OCSP response or an
1175     * OCSP signer. */
1176    int ret = mgs_create_ocsp_trust_list(
1177        ocsp->trust, &(sc->certs_x509_crt_chain[idx + 1]), 1);
1178    if (ret != GNUTLS_E_SUCCESS)
1179    {
1180        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, server,
1181                     "Could not create OCSP trust list: %s (%d)",
1182                     gnutls_strerror(ret), ret);
1183        return "Could not build trust list for OCSP stapling!";
1184    }
1185    /* deinit trust list when the config pool is destroyed */
1186    apr_pool_cleanup_register(pconf, ocsp->trust,
1187                              mgs_cleanup_trust_list,
1188                              apr_pool_cleanup_null);
1189    return NULL;
1190}
1191
1192
1193
1194const char* mgs_ocsp_configure_stapling(apr_pool_t *pconf,
1195                                        apr_pool_t *ptemp __attribute__((unused)),
1196                                        server_rec *server)
1197{
1198    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
1199        ap_get_module_config(server->module_config, &gnutls_module);
1200
1201    if (sc->ocsp_cache == NULL)
1202        return "No OCSP response cache available, please check "
1203            "the GnuTLSOCSPCache setting.";
1204
1205    if (sc->certs_x509_chain_num < 2)
1206        return "No issuer (CA) certificate available, cannot enable "
1207            "stapling. Please add it to the GnuTLSCertificateFile.";
1208
1209    /* array for ocsp data, currently size 1 */
1210    sc->ocsp = apr_palloc(pconf, sizeof(mgs_ocsp_data_t) * (sc->certs_x509_chain_num - 1));
1211
1212    for (unsigned int i = 0; i < (sc->certs_x509_chain_num - 1); i++)
1213    {
1214        mgs_ocsp_data_t ocsp = apr_palloc(pconf, sizeof(struct mgs_ocsp_data));
1215
1216        const char *err = configure_cert_staple(ocsp, server, sc, i, pconf);
1217        if (err != NULL)
1218        {
1219            gnutls_datum_t dn;
1220            gnutls_x509_crt_get_dn3(sc->certs_x509_crt_chain[i], &dn, 0);
1221            /* If stapling is enabled it MUST work for the server
1222             * certificate itself, errors for others are
1223             * ignored. Either way log a warning. */
1224            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, server,
1225                         "Could not create OCSP stapling configuration "
1226                         "for certificate %u in chain (%s): %s",
1227                         i, (char*) dn.data, err);
1228            gnutls_free(dn.data);
1229            if (i == 0)
1230                return err;
1231            else
1232                break;
1233        }
1234
1235        sc->ocsp[i] = ocsp;
1236        sc->ocsp_num = i + 1;
1237    }
1238
1239    ap_log_error(APLOG_MARK, APLOG_INFO, 0, server,
1240                 "Configured OCSP stapling for %u certificates for %s:%d.",
1241                 sc->ocsp_num,
1242                 server->server_hostname, server->addrs->host_port);
1243    return NULL;
1244}
1245
1246
1247
1248/*
1249 * Like in the general post_config hook the HTTP status codes for
1250 * errors are just for fun. What matters is "neither OK nor DECLINED"
1251 * to denote an error.
1252 */
1253int mgs_ocsp_enable_stapling(apr_pool_t *pconf __attribute__((unused)),
1254                             apr_pool_t *ptemp __attribute__((unused)),
1255                             server_rec *server)
1256{
1257    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
1258        ap_get_module_config(server->module_config, &gnutls_module);
1259    if (sc->ocsp == NULL)
1260    {
1261        ap_log_error(APLOG_MARK, APLOG_STARTUP, APR_EGENERAL, server,
1262                     "CRITICAL ERROR: %s called with uninitialized OCSP "
1263                     "data structure. This indicates a bug in mod_gnutls.",
1264                     __func__);
1265        return HTTP_INTERNAL_SERVER_ERROR;
1266    }
1267
1268    /* set default values for unset parameters */
1269    if (sc->ocsp_auto_refresh == GNUTLS_ENABLED_UNSET)
1270        sc->ocsp_auto_refresh = GNUTLS_ENABLED_TRUE;
1271    if (sc->ocsp_check_nonce == GNUTLS_ENABLED_UNSET)
1272        sc->ocsp_check_nonce = GNUTLS_ENABLED_FALSE;
1273    if (sc->ocsp_cache_time == MGS_TIMEOUT_UNSET)
1274        sc->ocsp_cache_time = apr_time_from_sec(MGS_OCSP_CACHE_TIMEOUT);
1275    if (sc->ocsp_failure_timeout == MGS_TIMEOUT_UNSET)
1276        sc->ocsp_failure_timeout = apr_time_from_sec(MGS_OCSP_FAILURE_TIMEOUT);
1277    if (sc->ocsp_socket_timeout == MGS_TIMEOUT_UNSET)
1278        sc->ocsp_socket_timeout = apr_time_from_sec(MGS_OCSP_SOCKET_TIMEOUT);
1279    /* Base fuzz is half the configured maximum, the actual fuzz is
1280     * between the maximum and half that. The default maximum is
1281     * sc->ocsp_cache_time / 8, or twice the failure timeout,
1282     * whichever is larger (so the default guarantees at least one
1283     * retry before the cache entry expires).*/
1284    if (sc->ocsp_fuzz_time == MGS_TIMEOUT_UNSET)
1285    {
1286        sc->ocsp_fuzz_time = sc->ocsp_cache_time / 16;
1287        if (sc->ocsp_fuzz_time < sc->ocsp_failure_timeout)
1288            sc->ocsp_fuzz_time = sc->ocsp_failure_timeout;
1289    }
1290    else
1291        sc->ocsp_fuzz_time = sc->ocsp_fuzz_time / 2;
1292
1293    /* This really shouldn't happen considering MAX_FUZZ_BASE is about
1294     * 4.5 years, but better safe than sorry. */
1295    if (sc->ocsp_fuzz_time > MAX_FUZZ_BASE)
1296    {
1297        ap_log_error(APLOG_MARK, APLOG_STARTUP, APR_EINVAL, server,
1298                     "%s: Maximum fuzz time is too large, maximum "
1299                     "supported value is %" APR_INT64_T_FMT " seconds",
1300                     __func__, apr_time_sec(MAX_FUZZ_BASE) * 2);
1301        return HTTP_INTERNAL_SERVER_ERROR;
1302    }
1303
1304    /* The watchdog structure may be NULL if mod_watchdog is
1305     * unavailable. */
1306    if (sc->singleton_wd != NULL
1307        && sc->ocsp_auto_refresh == GNUTLS_ENABLED_TRUE)
1308    {
1309        /* register an update callback for each certificate configured
1310         * for stapling */
1311        for (unsigned int i = 0; i < sc->ocsp_num; i++)
1312        {
1313            apr_status_t rv =
1314                sc->singleton_wd->register_callback(sc->singleton_wd->wd,
1315                                                    sc->ocsp_cache_time,
1316                                                    sc->ocsp[i],
1317                                                    mgs_async_ocsp_update);
1318            if (rv == APR_SUCCESS)
1319                ap_log_error(APLOG_MARK, APLOG_INFO, rv, server,
1320                             "Enabled async OCSP update via watchdog "
1321                             "for %s:%d, cert[%u]",
1322                             server->server_hostname, server->addrs->host_port,
1323                             i);
1324            else
1325                ap_log_error(APLOG_MARK, APLOG_WARNING, rv, server,
1326                             "Enabling async OCSP update via watchdog "
1327                             "for %s:%d, cert[%u] failed!",
1328                             server->server_hostname, server->addrs->host_port,
1329                             i);
1330        }
1331    }
1332
1333    return OK;
1334}
Note: See TracBrowser for help on using the repository browser.