source: mod_gnutls/src/gnutls_ocsp.c @ bac1a32

debian/masterproxy-ticket
Last change on this file since bac1a32 was bac1a32, checked in by Fiona Klute <fiona.klute@…>, 22 months ago

Order, log message, and style fixes

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