source: mod_gnutls/src/gnutls_ocsp.c @ 11e6205

debian/masterdebian/stretch-backportsupstream
Last change on this file since 11e6205 was d6834e0, checked in by Thomas Klute <thomas2.klute@…>, 3 years ago

OCSP refresh mutex: Prevent parallel requests

Add a global mutex which a thread must hold before updating a cached
OCSP response. This avoids two threads updating the same response in
parallel. The impact of parallel updates may be small with the
experimental file-based mechanism, but an extra OCSP request over HTTP
would add a lot of overhead.

Note that the new 'gnutls-ocsp' mutex is a global mutex, not one per
virtual host, because a mutex must be registered in pre_config for the
Mutex directive to work.

  • Property mode set to 100644
File size: 20.3 KB
Line 
1/**
2 *  Copyright 2016 Thomas Klute
3 *
4 *  Licensed under the Apache License, Version 2.0 (the "License");
5 *  you may not use this file except in compliance with the License.
6 *  You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 *  Unless required by applicable law or agreed to in writing, software
11 *  distributed under the License is distributed on an "AS IS" BASIS,
12 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 *  See the License for the specific language governing permissions and
14 *  limitations under the License.
15 */
16
17#include "gnutls_ocsp.h"
18#include "mod_gnutls.h"
19#include "gnutls_cache.h"
20
21#include <apr_lib.h>
22#include <apr_time.h>
23#include <gnutls/ocsp.h>
24#include <time.h>
25
26#ifdef APLOG_USE_MODULE
27APLOG_USE_MODULE(gnutls);
28#endif
29
30
31
32#define _log_one_ocsp_fail(str, srv)                                    \
33    ap_log_error(APLOG_MARK, APLOG_INFO, APR_EGENERAL, (srv),           \
34                 "Reason for failed OCSP response verification: %s", (str))
35/*
36 * Log all matching reasons for verification failure
37 */
38static void _log_verify_fail_reason(const unsigned int verify, server_rec *s)
39{
40    if (verify & GNUTLS_OCSP_VERIFY_SIGNER_NOT_FOUND)
41        _log_one_ocsp_fail("Signer cert not found", s);
42
43    if (verify & GNUTLS_OCSP_VERIFY_SIGNER_KEYUSAGE_ERROR)
44        _log_one_ocsp_fail("Signer cert keyusage error", s);
45
46    if (verify & GNUTLS_OCSP_VERIFY_UNTRUSTED_SIGNER)
47        _log_one_ocsp_fail("Signer cert is not trusted", s);
48
49    if (verify & GNUTLS_OCSP_VERIFY_INSECURE_ALGORITHM)
50        _log_one_ocsp_fail("Insecure algorithm", s);
51
52    if (verify & GNUTLS_OCSP_VERIFY_SIGNATURE_FAILURE)
53        _log_one_ocsp_fail("Signature failure", s);
54
55    if (verify & GNUTLS_OCSP_VERIFY_CERT_NOT_ACTIVATED)
56        _log_one_ocsp_fail("Signer cert not yet activated", s);
57
58    if (verify & GNUTLS_OCSP_VERIFY_CERT_EXPIRED)
59        _log_one_ocsp_fail("Signer cert expired", s);
60}
61
62
63
64const char *mgs_store_ocsp_response_path(cmd_parms *parms,
65                                         void *dummy __attribute__((unused)),
66                                         const char *arg)
67{
68    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
69        ap_get_module_config(parms->server->module_config, &gnutls_module);
70
71    sc->ocsp_response_file = ap_server_root_relative(parms->pool, arg);
72    return NULL;
73}
74
75
76
77/**
78 * Check if the time specified in the nextUpdate field (if any) of the
79 * given OCSP response has passed. Returns GNUTLS_E_SUCCESS if it has
80 * not (so the response is still valid), or there is no such field.
81 *
82 * Note that this function does not do a signature check, it is meant
83 * to operate on cached responses that have been verified before.
84 */
85static int check_ocsp_response_expiry(mgs_handle_t *ctxt,
86                                      const gnutls_datum_t *ocsp_response)
87{
88    gnutls_ocsp_resp_t resp;
89    int ret = gnutls_ocsp_resp_init(&resp);
90    if (ret != GNUTLS_E_SUCCESS)
91    {
92        ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c,
93                      "Could not initialize OCSP response structure: "
94                      "%s (%d)", gnutls_strerror(ret), ret);
95        goto resp_cleanup;
96    }
97    ret = gnutls_ocsp_resp_import(resp, ocsp_response);
98    if (ret != GNUTLS_E_SUCCESS)
99    {
100        ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c,
101                      "Importing OCSP response failed: %s (%d)",
102                      gnutls_strerror(ret), ret);
103        goto resp_cleanup;
104    }
105    time_t next_update;
106    ret = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL, NULL, NULL,
107                                      NULL, &next_update, NULL, NULL);
108    if (ret != GNUTLS_E_SUCCESS)
109    {
110        ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c,
111                      "Could not get OCSP response data: %s (%d)",
112                      gnutls_strerror(ret), ret);
113        goto resp_cleanup;
114    }
115
116    if (next_update == (time_t) -1)
117    {
118        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ctxt->c,
119                      "OSCP response does not contain nextUpdate info.");
120    }
121    else
122    {
123        apr_time_t now = apr_time_now();
124        apr_time_t valid_to;
125        apr_time_ansi_put(&valid_to, next_update);
126        if (now > valid_to)
127        {
128            char date_str[APR_RFC822_DATE_LEN];
129            apr_rfc822_date(date_str, valid_to);
130            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ctxt->c,
131                          "OCSP response has expired at %s.", date_str);
132            ret = GNUTLS_E_OCSP_RESPONSE_ERROR;
133            goto resp_cleanup;
134        }
135    }
136 resp_cleanup:
137    gnutls_ocsp_resp_deinit(resp);
138    return ret;
139}
140
141
142
143/**
144 * Check if the provided OCSP response is usable for stapling in
145 * connections to this server. Returns GNUTLS_E_SUCCESS if yes.
146 *
147 * Supports only one certificate status per response.
148 *
149 * If expiry is not NULL, it will be set to the nextUpdate time
150 * contained in the response, or zero the response does not contain a
151 * nextUpdate field.
152 */
153int check_ocsp_response(server_rec *s, const gnutls_datum_t *ocsp_response,
154                        apr_time_t* expiry)
155{
156    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
157        ap_get_module_config(s->module_config, &gnutls_module);
158
159    if (sc->ocsp_trust == NULL)
160    {
161        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
162                     "No OCSP trust list available for server \"%s\"!",
163                     s->server_hostname);
164        return GNUTLS_E_NO_CERTIFICATE_FOUND;
165    }
166
167    gnutls_ocsp_resp_t resp;
168    int ret = gnutls_ocsp_resp_init(&resp);
169    if (ret != GNUTLS_E_SUCCESS)
170    {
171        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
172                     "Could not initialize OCSP response structure: %s (%d)",
173                     gnutls_strerror(ret), ret);
174        goto resp_cleanup;
175    }
176    ret = gnutls_ocsp_resp_import(resp, ocsp_response);
177    if (ret != GNUTLS_E_SUCCESS)
178    {
179        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
180                     "Importing OCSP response failed: %s (%d)",
181                     gnutls_strerror(ret), ret);
182        goto resp_cleanup;
183    }
184
185    ret = gnutls_ocsp_resp_check_crt(resp, 0, sc->certs_x509_crt_chain[0]);
186    if (ret != GNUTLS_E_SUCCESS)
187    {
188        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
189                     "OCSP response is not for server certificate: %s (%d)",
190                     gnutls_strerror(ret), ret);
191        goto resp_cleanup;
192    }
193
194    unsigned int verify;
195    ret = gnutls_ocsp_resp_verify(resp, *(sc->ocsp_trust), &verify, 0);
196    if (ret != GNUTLS_E_SUCCESS)
197    {
198        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
199                     "OCSP response verification failed: %s (%d)",
200                     gnutls_strerror(ret), ret);
201        goto resp_cleanup;
202    }
203    else
204    {
205        /* verification worked, check the result */
206        if (verify != 0)
207        {
208            _log_verify_fail_reason(verify, s);
209            ret = GNUTLS_E_OCSP_RESPONSE_ERROR;
210            goto resp_cleanup;
211        }
212        else
213            ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, s,
214                         "OCSP response is valid.");
215    }
216
217    /* OK, response is for our certificate and valid, let's get the
218     * actual response data. */
219    unsigned int cert_status;
220    time_t this_update;
221    time_t next_update;
222    ret = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL, NULL,
223                                      &cert_status, &this_update,
224                                      &next_update, NULL, NULL);
225    if (ret != GNUTLS_E_SUCCESS)
226    {
227        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
228                     "Could not get OCSP response data: %s (%d)",
229                     gnutls_strerror(ret), ret);
230        goto resp_cleanup;
231    }
232
233    apr_time_t now = apr_time_now();
234    apr_time_t valid_at;
235    apr_time_ansi_put(&valid_at, this_update);
236    /* Buffer for human-readable times produced by apr_rfc822_date,
237     * see apr_time.h */
238    char date_str[APR_RFC822_DATE_LEN];
239    apr_rfc822_date(date_str, valid_at);
240
241    if (now < valid_at)
242    {
243        /* We don't know if our clock or that of the OCSP responder is
244         * out of sync, so warn but continue. */
245        ap_log_error(APLOG_MARK, APLOG_WARNING, APR_EGENERAL, s,
246                     "OSCP response claims to be from future (%s), check "
247                     "time synchronization!", date_str);
248    }
249
250    if (next_update == (time_t) -1)
251    {
252        ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, s,
253                     "OSCP response does not contain nextUpdate info.");
254        if (expiry != NULL)
255            *expiry = 0;
256    }
257    else
258    {
259        apr_time_t valid_to;
260        apr_time_ansi_put(&valid_to, next_update);
261        if (expiry != NULL)
262            *expiry = valid_to;
263        if (now > valid_to)
264        {
265            apr_rfc822_date(date_str, valid_to);
266            ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
267                         "OCSP response has expired at %s!", date_str);
268            /* Do not send a stale response */
269            ret = GNUTLS_E_OCSP_RESPONSE_ERROR;
270            goto resp_cleanup;
271        }
272    }
273
274    /* What's the actual status? Will be one of
275     * gnutls_ocsp_cert_status_t as defined in gnutls/ocsp.h. */
276    if (cert_status == GNUTLS_OCSP_CERT_GOOD)
277    {
278        /* Yay, everything's good! */
279        ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, s,
280                     "CA flagged certificate as valid at %s.", date_str);
281    }
282    else
283    {
284        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
285                     "CA flagged certificate as %s at %s.",
286                     cert_status == GNUTLS_OCSP_CERT_REVOKED ?
287                     "revoked" : "unknown", date_str);
288        ret = GNUTLS_E_OCSP_RESPONSE_ERROR;
289    }
290
291 resp_cleanup:
292    gnutls_ocsp_resp_deinit(resp);
293    return ret;
294}
295
296
297
298/*
299 * Returns the certificate fingerprint, memory is allocated from p.
300 */
301static gnutls_datum_t mgs_get_cert_fingerprint(apr_pool_t *p,
302                                               gnutls_x509_crt_t cert)
303{
304    gnutls_datum_t fingerprint = {NULL, 0};
305    size_t fplen;
306    gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, NULL, &fplen);
307    unsigned char * fp = apr_palloc(p, fplen);
308    gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, fp, &fplen);
309    /* Safe integer type conversion: The types of fingerprint.size
310     * (unsigned int) and fplen (size_t) may have different
311     * lengths. */
312    if (__builtin_add_overflow(fplen, 0, &fingerprint.size))
313        fingerprint.size = 0;
314    else
315        fingerprint.data = fp;
316    return fingerprint;
317}
318
319
320
321/* TODO: response should be fetched from sc->ocsp_uri */
322apr_status_t mgs_cache_ocsp_response(server_rec *s)
323{
324    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
325        ap_get_module_config(s->module_config, &gnutls_module);
326
327    if (sc->cache == NULL)
328    {
329        /* OCSP caching requires a cache. */
330        return APR_ENOTIMPL;
331    }
332
333    apr_pool_t *tmp;
334    apr_status_t rv = apr_pool_create(&tmp, NULL);
335    if (rv != APR_SUCCESS)
336    {
337        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
338                     "could not create temporary pool for %s",
339                     __func__);
340        return rv;
341    }
342
343    /* the fingerprint will be used as cache key */
344    gnutls_datum_t fingerprint =
345        mgs_get_cert_fingerprint(tmp, sc->certs_x509_crt_chain[0]);
346    if (fingerprint.data == NULL)
347        return APR_EINVAL;
348
349    ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, s,
350                 "Loading OCSP response from %s",
351                 sc->ocsp_response_file);
352    apr_file_t *file;
353    apr_finfo_t finfo;
354    apr_size_t br = 0;
355    rv = apr_file_open(&file, sc->ocsp_response_file,
356                       APR_READ | APR_BINARY, APR_OS_DEFAULT, tmp);
357    if (rv != APR_SUCCESS)
358    {
359        apr_pool_destroy(tmp);
360        return rv;
361    }
362    rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, file);
363    if (rv != APR_SUCCESS)
364    {
365        apr_pool_destroy(tmp);
366        return rv;
367    }
368
369    gnutls_datum_t resp;
370    resp.data = apr_palloc(tmp, finfo.size);
371    rv = apr_file_read_full(file, resp.data, finfo.size, &br);
372    if (rv != APR_SUCCESS)
373    {
374        apr_pool_destroy(tmp);
375        return rv;
376    }
377    apr_file_close(file);
378    /* safe integer type conversion */
379    if (__builtin_add_overflow(br, 0, &resp.size))
380    {
381        apr_pool_destroy(tmp);
382        return APR_EINVAL;
383    }
384
385    apr_time_t expiry;
386    if (check_ocsp_response(s, &resp, &expiry) != GNUTLS_E_SUCCESS)
387    {
388        ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_EGENERAL, s,
389                     "OCSP response validation failed, cannot "
390                     "update cache.");
391        apr_pool_destroy(tmp);
392        return APR_EGENERAL;
393    }
394    /* If expiry is zero, the response does not contain a nextUpdate
395     * field. Use the default cache timeout. */
396    if (expiry == 0)
397        expiry = apr_time_now() + sc->cache_timeout;
398    /* Apply grace time otherwise. */
399    else
400        expiry -= sc->ocsp_grace_time;
401
402    int r = sc->cache->store(s, fingerprint, resp, expiry);
403    /* destroy pool, and original copy of the OCSP response with it */
404    apr_pool_destroy(tmp);
405    if (r != 0)
406    {
407        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
408                      "Storing OCSP response in cache failed.");
409        return APR_EGENERAL;
410    }
411    return APR_SUCCESS;
412}
413
414
415
416int mgs_get_ocsp_response(gnutls_session_t session __attribute__((unused)),
417                          void *ptr,
418                          gnutls_datum_t *ocsp_response)
419{
420    mgs_handle_t *ctxt = (mgs_handle_t *) ptr;
421    if (ctxt->sc->cache == NULL)
422    {
423        /* OCSP caching requires a cache. */
424        return GNUTLS_E_NO_CERTIFICATE_STATUS;
425    }
426
427    gnutls_datum_t fingerprint =
428        mgs_get_cert_fingerprint(ctxt->c->pool,
429                                 ctxt->sc->certs_x509_crt_chain[0]);
430    if (fingerprint.data == NULL)
431        return GNUTLS_E_NO_CERTIFICATE_STATUS;
432
433    *ocsp_response = ctxt->sc->cache->fetch(ctxt, fingerprint);
434    if (ocsp_response->size == 0)
435    {
436        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_EGENERAL, ctxt->c,
437                      "Fetching OCSP response from cache failed.");
438    }
439    else
440    {
441        if (check_ocsp_response_expiry(ctxt, ocsp_response)
442            == GNUTLS_E_SUCCESS)
443            return GNUTLS_E_SUCCESS;
444    }
445    /* get rid of invalid response (if any) */
446    gnutls_free(ocsp_response->data);
447    ocsp_response->data = NULL;
448
449    /* If the cache had no response or an invalid one, try to update. */
450    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ctxt->c,
451                  "No valid OCSP response in cache, trying to update.");
452
453    apr_status_t rv = apr_global_mutex_trylock(ctxt->sc->ocsp_mutex);
454    if (APR_STATUS_IS_EBUSY(rv))
455    {
456        /* Another thread is currently holding the mutex, wait. */
457        apr_global_mutex_lock(ctxt->sc->ocsp_mutex);
458        /* Check if this other thread updated the response we need. It
459         * would be better to have a vhost specific mutex, but at the
460         * moment there's no good way to integrate that with the
461         * Apache Mutex directive. */
462        *ocsp_response = ctxt->sc->cache->fetch(ctxt, fingerprint);
463        if (ocsp_response->size > 0
464            && check_ocsp_response_expiry(ctxt, ocsp_response)
465            == GNUTLS_E_SUCCESS)
466        {
467            /* Got a valid response now, unlock mutex and return. */
468            apr_global_mutex_unlock(ctxt->sc->ocsp_mutex);
469            return GNUTLS_E_SUCCESS;
470        }
471        else
472        {
473            gnutls_free(ocsp_response->data);
474            ocsp_response->data = NULL;
475        }
476    }
477
478    rv = mgs_cache_ocsp_response(ctxt->c->base_server);
479    if (rv != APR_SUCCESS)
480    {
481        ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, ctxt->c,
482                      "Updating OCSP response cache failed");
483        apr_global_mutex_unlock(ctxt->sc->ocsp_mutex);
484        goto fail_cleanup;
485    }
486    apr_global_mutex_unlock(ctxt->sc->ocsp_mutex);
487
488    /* retry reading from cache */
489    *ocsp_response = ctxt->sc->cache->fetch(ctxt, fingerprint);
490    if (ocsp_response->size == 0)
491    {
492        ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c,
493                      "Fetching OCSP response from cache failed on retry.");
494    }
495    else
496    {
497        /* Succeed if response is present and valid. */
498        if (check_ocsp_response_expiry(ctxt, ocsp_response)
499            == GNUTLS_E_SUCCESS)
500            return GNUTLS_E_SUCCESS;
501    }
502
503    /* failure, clean up response data */
504 fail_cleanup:
505    gnutls_free(ocsp_response->data);
506    ocsp_response->size = 0;
507    ocsp_response->data = NULL;
508    return GNUTLS_E_NO_CERTIFICATE_STATUS;
509}
510
511
512
513int mgs_create_ocsp_trust_list(gnutls_x509_trust_list_t *tl,
514                               const gnutls_x509_crt_t *chain,
515                               const int num)
516{
517    int added = 0;
518    int ret = gnutls_x509_trust_list_init(tl, num);
519
520    if (ret == GNUTLS_E_SUCCESS)
521        added = gnutls_x509_trust_list_add_cas(*tl, chain, num, 0);
522
523    if (added != num)
524        ret = GNUTLS_E_CERTIFICATE_ERROR;
525
526    /* Clean up trust list in case of error */
527    if (ret != GNUTLS_E_SUCCESS)
528        gnutls_x509_trust_list_deinit(*tl, 0);
529
530    return ret;
531}
532
533
534
535apr_status_t mgs_cleanup_trust_list(void *data)
536{
537    gnutls_x509_trust_list_t *tl = (gnutls_x509_trust_list_t *) data;
538    gnutls_x509_trust_list_deinit(*tl, 0);
539    return APR_SUCCESS;
540}
541
542
543
544apr_uri_t * mgs_cert_get_ocsp_uri(apr_pool_t *p, gnutls_x509_crt_t cert)
545{
546    apr_pool_t *tmp;
547    apr_status_t rv = apr_pool_create(&tmp, p);
548    if (rv != APR_SUCCESS)
549        return NULL;
550
551    apr_uri_t *ocsp_uri = NULL;
552
553    int ret = GNUTLS_E_SUCCESS;
554    /* search authority info access for OCSP URI */
555    for (int seq = 0; ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; seq++)
556    {
557        gnutls_datum_t ocsp_access_data;
558        ret = gnutls_x509_crt_get_authority_info_access(cert, seq,
559                                                        GNUTLS_IA_OCSP_URI,
560                                                        &ocsp_access_data,
561                                                        NULL);
562        if (ret == GNUTLS_E_SUCCESS)
563        {
564            /* create NULL terminated string */
565            char *ocsp_str =
566                apr_pstrndup(tmp, (const char*) ocsp_access_data.data,
567                             ocsp_access_data.size);
568            gnutls_free(ocsp_access_data.data);
569
570            ocsp_uri = apr_palloc(p, sizeof(apr_uri_t));
571            rv = apr_uri_parse(p, ocsp_str, ocsp_uri);
572            if (rv == APR_SUCCESS)
573                break;
574            else
575                ocsp_uri = NULL;
576        }
577    }
578
579    apr_pool_destroy(tmp);
580    return ocsp_uri;
581}
582
583
584
585/*
586 * Like in the general post_config hook the HTTP status codes for
587 * errors are just for fun. What matters is "neither OK nor DECLINED"
588 * to denote an error.
589 */
590int mgs_ocsp_post_config_server(apr_pool_t *pconf,
591                                apr_pool_t *ptemp __attribute__((unused)),
592                                server_rec *server)
593{
594    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
595        ap_get_module_config(server->module_config, &gnutls_module);
596
597    if (sc->certs_x509_chain_num < 2)
598    {
599        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, server,
600                     "OCSP stapling is enabled but no CA certificate "
601                     "available for %s:%d, make sure it is included in "
602                     "GnuTLSCertificateFile!",
603                     server->server_hostname, server->addrs->host_port);
604        return HTTP_NOT_FOUND;
605    }
606
607    sc->ocsp_uri = mgs_cert_get_ocsp_uri(pconf, sc->certs_x509_crt_chain[0]);
608
609    sc->ocsp_trust = apr_palloc(pconf,
610                                sizeof(gnutls_x509_trust_list_t));
611     /* Only the direct issuer may sign the OCSP response or an OCSP
612      * signer. */
613    int ret = mgs_create_ocsp_trust_list(sc->ocsp_trust,
614                                         &(sc->certs_x509_crt_chain[1]),
615                                         1);
616    if (ret != GNUTLS_E_SUCCESS)
617    {
618        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, server,
619                     "Could not create OCSP trust list: %s (%d)",
620                     gnutls_strerror(ret), ret);
621        return HTTP_INTERNAL_SERVER_ERROR;
622    }
623    /* deinit trust list when the config pool is destroyed */
624    apr_pool_cleanup_register(pconf, sc->ocsp_trust,
625                              mgs_cleanup_trust_list,
626                              apr_pool_cleanup_null);
627
628    return OK;
629}
Note: See TracBrowser for help on using the repository browser.