source: mod_gnutls/src/gnutls_ocsp.c @ de9b100

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

OCSP config: Check if cache is available before processing certificate

It doesn't really matter with the current function that handles only
one certificate, but when configuring stapling for the whole
certificate chain it will.

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