source: mod_gnutls/src/gnutls_ocsp.c @ a8374f7

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

Keep a reference to the certificate with OCSP data

When implementing multi-staple there will be a bunch of OCSP data
structures per virtual host. This will make it possible to handle
these without complex algorithms to connect certificate index with
OCSP data.

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