Changeset 2246a84 in mod_gnutls


Ignore:
Timestamp:
Apr 21, 2018, 3:51:51 PM (3 years ago)
Author:
Fiona Klute <fiona.klute@…>
Branches:
debian/master, master, proxy-ticket
Children:
7921dc7
Parents:
fa6d0bb
Message:

Make automatic OCSP cache updates and fuzz time configurable

Files:
6 edited

Legend:

Unmodified
Added
Removed
  • doc/mod_gnutls_manual.mdwn

    rfa6d0bb r2246a84  
    44
    55`mod_gnutls` is a module for the Apache web server that provides HTTPS
    6 (HTTP over Transport Layer Security (TLS) or the older Secure Sockets
    7 Layer (SSL)) using the GnuTLS library.  More information about the
    8 module can be found at [the project's website](https://mod.gnutls.org/).
     6(HTTP over Transport Layer Security (TLS)) using the GnuTLS library.
     7More information about the module can be found at
     8[the project's website](https://mod.gnutls.org/).
    99
    1010* * * * *
     
    568568OCSP cache updates are serialized using the `gnutls-ocsp` mutex.
    569569
     570### GnuTLSOCSPAutoRefresh
     571
     572Regularly refresh cached OCSP response independent of TLS handshakes?
     573
     574    GnuTLSOCSPAutoRefresh [On|Off]
     575
     576Default: *on*\
     577Context: server config, virtual host
     578
     579By default `mod_gnutls` will regularly refresh the cached OCSP
     580response for hosts that have OCSP stapling enabled, regardless of
     581whether it is used. This has advantages over updating the OCSP
     582response only if a TLS handshake needs it:
     583
     584* Updating the cached response before it expires can hide short
     585  unavailability of the OCSP responder, if a repeated request is
     586  successful before the cache expires (see below).
     587
     588* Handshakes are not slowed down by fetching responses.
     589
     590The interval to the next request is determined as follows: After a
     591successful OCSP request the next one is scheduled for a random period
     592between `GnuTLSOCSPFuzzTime` and half of it before
     593`GnuTLSOCSPCacheTimeout` expires. For example, if the cache timeout is
     5943600 seconds and the fuzz time 600 seconds, the next request will be
     595sent after 3000 to 3300 seconds. If the validity period of the
     596response expires before then, the selected interval is halved until it
     597is smaller than the time until expiry. If an OCSP request fails, it is
     598retried after `GnuTLSOCSPFailureTimeout`.
     599
     600Regularly updating the OCSP cache requires `mod_watchdog`,
     601`mod_gnutls` will fall back to updating the OCSP cache during
     602handshakes if `mod_watchdog` is not available or this option is set to
     603`Off`.
     604
    570605### GnuTLSOCSPCheckNonce
    571606
     
    640675one means that stapling will remain disabled for longer after a failed
    641676request.
     677
     678### GnuTLSOCSPFuzzTime
     679
     680Update the cached OCSP response up to this time before the cache expires
     681
     682    GnuTLSOCSPFuzzTime SECONDS
     683
     684Default: *larger of GnuTLSOCSPCacheTimeout / 8 and GnuTLSOCSPFailureTimeout \* 2*\
     685Context: server config, virtual host
     686
     687Refreshing the cached response before it expires hides short OCSP
     688responder unavailability. See `GnuTLSOCSPAutoRefresh` for how this
     689value is used, using at least twice `GnuTLSOCSPFailureTimeout` is
     690recommended.
    642691
    643692### GnuTLSOCSPSocketTimeout
  • include/mod_gnutls.h.in

    rfa6d0bb r2246a84  
    214214    /* Enable OCSP stapling */
    215215    unsigned char ocsp_staple;
     216    /* Automatically refresh cached OCSP response? */
     217    unsigned char ocsp_auto_refresh;
    216218    /* Check nonce in OCSP responses? */
    217219    unsigned char ocsp_check_nonce;
     
    228230    /* If an OCSP request fails wait this long before trying again. */
    229231    apr_interval_time_t ocsp_failure_timeout;
     232    /** How long before a cached OCSP response expires should it be
     233     * updated? During configuration parsing this is set to the
     234     * maximum, during post configuration the value will be set to
     235     * half that. After each update the interval to for the next one
     236     * is choosen randomly as `ocsp_fuzz_time + ocsp_fuzz_time *
     237     * RANDOM` with `0 <= RANDOM <= 1`. */
     238    apr_interval_time_t ocsp_fuzz_time;
    230239    /* Socket timeout for OCSP requests */
    231240    apr_interval_time_t ocsp_socket_timeout;
  • src/gnutls_config.c

    rfa6d0bb r2246a84  
    33 *  Copyright 2008, 2014 Nikos Mavrogiannopoulos
    44 *  Copyright 2011 Dash Shendy
    5  *  Copyright 2015-2016 Fiona Klute
     5 *  Copyright 2015-2018 Fiona Klute
    66 *
    77 *  Licensed under the Apache License, Version 2.0 (the "License");
     
    851851                                "GnuTLSOCSPFailureTimeout"))
    852852        sc->ocsp_failure_timeout = apr_time_from_sec(argint);
     853    else if (!apr_strnatcasecmp(parms->directive->directive,
     854                                "GnuTLSOCSPFuzzTime"))
     855        sc->ocsp_fuzz_time = apr_time_from_sec(argint);
    853856    else if (!apr_strnatcasecmp(parms->directive->directive,
    854857                                "GnuTLSOCSPSocketTimeout"))
     
    11051108
    11061109    sc->ocsp_staple = GNUTLS_ENABLED_UNSET;
     1110    sc->ocsp_auto_refresh = GNUTLS_ENABLED_UNSET;
    11071111    sc->ocsp_check_nonce = GNUTLS_ENABLED_UNSET;
    11081112    sc->ocsp_response_file = NULL;
     
    11101114    sc->ocsp_cache_time = MGS_TIMEOUT_UNSET;
    11111115    sc->ocsp_failure_timeout = MGS_TIMEOUT_UNSET;
     1116    sc->ocsp_fuzz_time = MGS_TIMEOUT_UNSET;
    11121117    sc->ocsp_socket_timeout = MGS_TIMEOUT_UNSET;
    11131118
     
    11711176
    11721177    gnutls_srvconf_merge(ocsp_staple, GNUTLS_ENABLED_UNSET);
     1178    gnutls_srvconf_merge(ocsp_auto_refresh, GNUTLS_ENABLED_UNSET);
    11731179    gnutls_srvconf_merge(ocsp_check_nonce, GNUTLS_ENABLED_UNSET);
    11741180    gnutls_srvconf_assign(ocsp_response_file);
    11751181    gnutls_srvconf_merge(ocsp_cache_time, MGS_TIMEOUT_UNSET);
    11761182    gnutls_srvconf_merge(ocsp_failure_timeout, MGS_TIMEOUT_UNSET);
     1183    gnutls_srvconf_merge(ocsp_fuzz_time, MGS_TIMEOUT_UNSET);
    11771184    gnutls_srvconf_merge(ocsp_socket_timeout, MGS_TIMEOUT_UNSET);
    11781185
  • src/gnutls_ocsp.c

    rfa6d0bb r2246a84  
    8686    else
    8787        sc->ocsp_staple = GNUTLS_ENABLED_FALSE;
     88
     89    return NULL;
     90}
     91
     92
     93
     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;
    88105
    89106    return NULL;
     
    929946
    930947
    931 /** The maximum random fuzz interval that will not overflow. The
    932  * permitted values are limited to whatever will not make an
    933  * `apr_interval_time_t` variable overflow when multiplied with
    934  * `APR_UINT16_MAX`. With apr_interval_time_t being a 64 bit signed
    935  * integer the maximum fuzz interval is about 4.5 years, which should
    936  * be more than plenty. */
    937 #define MAX_FUZZ_TIME (APR_INT64_MAX / APR_UINT16_MAX)
     948/** The maximum random fuzz base (half the maximum fuzz) that will not
     949 * overflow. The permitted values are limited to whatever will not
     950 * make an `apr_interval_time_t` variable overflow when multiplied
     951 * with `APR_UINT16_MAX`. With apr_interval_time_t being a 64 bit
     952 * signed integer the maximum fuzz interval is about 4.5 years, which
     953 * should be more than plenty. */
     954#define MAX_FUZZ_BASE (APR_INT64_MAX / APR_UINT16_MAX)
    938955
    939956/**
     
    972989    apr_status_t rv = mgs_cache_ocsp_response(server, &expiry);
    973990
    974     /* TODO: Make maximum fuzz time configurable and compare to
    975      * allowed maximum during config */
    976     ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, server,
    977                  "%s: Maximum fuzz time without overflow: %" APR_INT64_T_FMT
    978                  " seconds",
    979                  __func__, apr_time_sec(MAX_FUZZ_TIME));
    980 
    981991    apr_interval_time_t next_interval;
    982992    if (rv != APR_SUCCESS)
     
    9981008        }
    9991009
    1000         /* Base fuzz is half the maximum (sc->ocsp_cache_time / 8 at
    1001          * the moment). The actual fuzz is between the maximum and
    1002          * half that. */
    1003         apr_interval_time_t base_fuzz = sc->ocsp_cache_time / 16;
    1004         apr_interval_time_t fuzz =
    1005             base_fuzz + base_fuzz * random_bytes / APR_UINT16_MAX;
     1010        /* Choose the fuzz interval for the next update between
     1011         * `sc->ocsp_fuzz_time` and twice that. */
     1012        apr_interval_time_t fuzz = sc->ocsp_fuzz_time
     1013            + (sc->ocsp_fuzz_time * random_bytes / APR_UINT16_MAX);
    10061014
    10071015        /* With an extremly short timeout or weird nextUpdate value
     
    10961104
    10971105    /* set default values for unset parameters */
     1106    if (sc->ocsp_auto_refresh == GNUTLS_ENABLED_UNSET)
     1107        sc->ocsp_auto_refresh = GNUTLS_ENABLED_TRUE;
    10981108    if (sc->ocsp_check_nonce == GNUTLS_ENABLED_UNSET)
    10991109        sc->ocsp_check_nonce = GNUTLS_ENABLED_TRUE;
     
    11041114    if (sc->ocsp_socket_timeout == MGS_TIMEOUT_UNSET)
    11051115        sc->ocsp_socket_timeout = apr_time_from_sec(MGS_OCSP_SOCKET_TIMEOUT);
     1116    /* Base fuzz is half the configured maximum, the actual fuzz is
     1117     * between the maximum and half that. The default maximum is
     1118     * sc->ocsp_cache_time / 8, or twice the failure timeout,
     1119     * whichever is larger (so the default guarantees at least one
     1120     * retry before the cache entry expires).*/
     1121    if (sc->ocsp_fuzz_time == MGS_TIMEOUT_UNSET)
     1122    {
     1123        sc->ocsp_fuzz_time = sc->ocsp_cache_time / 16;
     1124        if (sc->ocsp_fuzz_time < sc->ocsp_failure_timeout)
     1125            sc->ocsp_fuzz_time = sc->ocsp_failure_timeout;
     1126    }
     1127    else
     1128        sc->ocsp_fuzz_time = sc->ocsp_fuzz_time / 2;
     1129
     1130    /* This really shouldn't happen considering MAX_FUZZ_BASE is about
     1131     * 4.5 years, but better safe than sorry. */
     1132    if (sc->ocsp_fuzz_time > MAX_FUZZ_BASE)
     1133    {
     1134        ap_log_error(APLOG_MARK, APLOG_STARTUP, APR_EINVAL, server,
     1135                     "%s: Maximum fuzz time is too large, maximum "
     1136                     "supported value is %" APR_INT64_T_FMT " seconds",
     1137                     __func__, apr_time_sec(MAX_FUZZ_BASE) * 2);
     1138        return HTTP_INTERNAL_SERVER_ERROR;
     1139    }
    11061140
    11071141    sc->ocsp = apr_palloc(pconf, sizeof(struct mgs_ocsp_data));
     
    11501184    /* The watchdog structure may be NULL if mod_watchdog is
    11511185     * unavailable. */
    1152     if (sc->singleton_wd != NULL)
     1186    if (sc->singleton_wd != NULL
     1187        && sc->ocsp_auto_refresh == GNUTLS_ENABLED_TRUE)
    11531188    {
    11541189        apr_status_t rv =
  • src/gnutls_ocsp.h

    rfa6d0bb r2246a84  
    11/*
    2  *  Copyright 2016 Fiona Klute
     2 *  Copyright 2016-2018 Fiona Klute
    33 *
    44 *  Licensed under the Apache License, Version 2.0 (the "License");
     
    5454                                     const int arg);
    5555
     56const char *mgs_set_ocsp_auto_refresh(cmd_parms *parms,
     57                                      void *dummy __attribute__((unused)),
     58                                      const int arg);
     59
    5660const char *mgs_set_ocsp_check_nonce(cmd_parms *parms,
    5761                                     void *dummy __attribute__((unused)),
  • src/mod_gnutls.c

    rfa6d0bb r2246a84  
    370370                 NULL, RSRC_CONF,
    371371                 "Enable OCSP stapling"),
     372    AP_INIT_FLAG("GnuTLSOCSPAutoRefresh", mgs_set_ocsp_auto_refresh,
     373                 NULL, RSRC_CONF,
     374                 "Regularly refresh cached OCSP response independent "
     375                 "of TLS handshakes?"),
    372376    AP_INIT_FLAG("GnuTLSOCSPCheckNonce", mgs_set_ocsp_check_nonce,
    373377                 NULL, RSRC_CONF,
     
    385389                  "Wait this many seconds before retrying a failed OCSP "
    386390                  "request"),
     391    AP_INIT_TAKE1("GnuTLSOCSPFuzzTime", mgs_set_timeout,
     392                  NULL, RSRC_CONF,
     393                  "Update cached OCSP response up to this many seconds "
     394                  "before it expires, if GnuTLSOCSPAutoRefresh is enabled."),
    387395    AP_INIT_TAKE1("GnuTLSOCSPSocketTimeout", mgs_set_timeout,
    388396                  NULL, RSRC_CONF,
Note: See TracChangeset for help on using the changeset viewer.