diff --git a/src/cache/memcache.c b/src/cache/memcache.c index 9877aabd..b8f646b9 100644 --- a/src/cache/memcache.c +++ b/src/cache/memcache.c @@ -89,7 +89,7 @@ static int oidc_cache_memcache_post_config(server_rec *s) { apr_uint32_t min = 0; apr_uint32_t smax = 0; apr_uint32_t hmax = 0; - apr_uint32_t ttl = 0; + apr_interval_time_t ttl = 0; if (oidc_cfg_cache_memcache_servers_get(cfg) == NULL) { oidc_serror(s, "cache type is set to \"memcache\", but no valid " OIDCMemCacheServers @@ -148,9 +148,6 @@ static int oidc_cache_memcache_post_config(server_rec *s) { smax = 1; } } - if (ttl == 0) { - ttl = apr_time_from_sec(60); - } if (smax > hmax) { smax = hmax; } @@ -181,11 +178,11 @@ static int oidc_cache_memcache_post_config(server_rec *s) { if (port == 0) port = 11211; - oidc_sdebug(s, "creating server: %s:%d, min=%d, smax=%d, hmax=%d, ttl=%d", host_str, port, min, smax, + oidc_sdebug(s, "creating server: %s:%d, min=%d, smax=%d, hmax=%d, ttl=%" APR_TIME_T_FMT, host_str, port, min, smax, hmax, ttl); /* create the memcache server struct */ - rv = apr_memcache_server_create(p, host_str, port, min, smax, hmax, ttl, &st); + rv = apr_memcache_server_create(p, host_str, port, min, smax, hmax, (apr_uint32_t)ttl, &st); if (rv != APR_SUCCESS) { oidc_serror(s, "failed to create cache server: %s:%d", host_str, port); return HTTP_INTERNAL_SERVER_ERROR; diff --git a/src/cfg/cache.c b/src/cfg/cache.c index 90140a47..82ce9c51 100644 --- a/src/cfg/cache.c +++ b/src/cfg/cache.c @@ -97,22 +97,28 @@ const char *oidc_cmd_cache_type_set(cmd_parms *cmd, void *ptr, const char *arg) return OIDC_CONFIG_DIR_RV(cmd, rv); \ } -#define OIDC_CFG_MEMBER_FUNCS_CACHE_INT_EXT(member, parse, def_val) \ +#define OIDC_CFG_MEMBER_FUNCS_CACHE_PARSE(member, type, parse, def_val) \ const char *oidc_cmd_cache_##member##_set(cmd_parms *cmd, void *ptr, const char *arg) { \ oidc_cfg_t *cfg = \ (oidc_cfg_t *)ap_get_module_config(cmd->server->module_config, &auth_openidc_module); \ - int v = -1; \ + type v = -1; \ const char *rv = parse; \ if (rv == NULL) \ cfg->cache.member = v; \ return OIDC_CONFIG_DIR_RV(cmd, rv); \ } \ \ - OIDC_CFG_MEMBER_FUNC_CACHE_TYPE_GET(member, int, def_val) + OIDC_CFG_MEMBER_FUNC_CACHE_TYPE_GET(member, type, def_val) + +#define OIDC_CFG_MEMBER_FUNCS_CACHE_INT_EXT(member, parse, def_val) \ + OIDC_CFG_MEMBER_FUNCS_CACHE_PARSE(member, int, parse, def_val) #define OIDC_CFG_MEMBER_FUNCS_CACHE_INT(member, min, max, def_val) \ OIDC_CFG_MEMBER_FUNCS_CACHE_INT_EXT(member, oidc_cfg_parse_int_min_max(cmd->pool, arg, &v, min, max), def_val) +#define OIDC_CFG_MEMBER_FUNCS_CACHE_TIMEOUT(member, min, max, def_val) \ + OIDC_CFG_MEMBER_FUNCS_CACHE_PARSE(member, apr_interval_time_t, oidc_cfg_parse_timeout_min_max(cmd->pool, arg, &v, min, max), def_val) + #define OIDC_CFG_MEMBER_FUNCS_CACHE_BOOL(member, def_val) \ OIDC_CFG_MEMBER_FUNCS_CACHE_INT_EXT(member, oidc_cfg_parse_boolean(cmd->pool, arg, &v), def_val) @@ -235,11 +241,17 @@ OIDC_CFG_MEMBER_FUNCS_CACHE_INT(memcache_smax, OIDC_CACHE_MEMCACHE_CONNECTIONS_S OIDC_CFG_MEMBER_FUNCS_CACHE_INT(memcache_hmax, OIDC_CACHE_MEMCACHE_CONNECTIONS_HMAX_MIN, OIDC_CACHE_MEMCACHE_CONNECTIONS_HMAX_MAX, OIDC_DEFAULT_CACHE_MEMCACHE_CONNECTIONS_HMAX) -#define OIDC_CACHE_MEMCACHE_CONNECTIONS_TTL_MIN 0 -#define OIDC_CACHE_MEMCACHE_CONNECTIONS_TTL_MAX 3600 * 24 * 7 -#define OIDC_DEFAULT_CACHE_MEMCACHE_CONNECTIONS_TTL 0 +#define OIDC_CACHE_MEMCACHE_CONNECTIONS_TTL_MIN (apr_interval_time_t)0 +/* + * Due to a design error in the apr-util 1.x apr_memcache_server_create prototype + * (it uses an apr_uint32_t instead of an apr_interval_time_t) we need to limit + * the maximum value to 4292 seconds which is the maximum value in microseconds + * that can be represented by an apr_uint32_t. + */ +#define OIDC_CACHE_MEMCACHE_CONNECTIONS_TTL_MAX apr_time_from_sec(4294) +#define OIDC_DEFAULT_CACHE_MEMCACHE_CONNECTIONS_TTL apr_time_from_sec(60) -OIDC_CFG_MEMBER_FUNCS_CACHE_INT(memcache_ttl, OIDC_CACHE_MEMCACHE_CONNECTIONS_TTL_MIN, +OIDC_CFG_MEMBER_FUNCS_CACHE_TIMEOUT(memcache_ttl, OIDC_CACHE_MEMCACHE_CONNECTIONS_TTL_MIN, OIDC_CACHE_MEMCACHE_CONNECTIONS_TTL_MAX, OIDC_DEFAULT_CACHE_MEMCACHE_CONNECTIONS_TTL) static void oidc_cfg_cache_memcache_create_server_config(oidc_cfg_t *c) { @@ -247,7 +259,7 @@ static void oidc_cfg_cache_memcache_create_server_config(oidc_cfg_t *c) { c->cache.memcache_min = OIDC_CONFIG_POS_INT_UNSET; c->cache.memcache_smax = OIDC_CONFIG_POS_INT_UNSET; c->cache.memcache_hmax = OIDC_CONFIG_POS_INT_UNSET; - c->cache.memcache_ttl = OIDC_CONFIG_POS_INT_UNSET; + c->cache.memcache_ttl = OIDC_CONFIG_POS_TIMEOUT_UNSET; } static void oidc_cfg_cache_memcache_merge_server_config(oidc_cfg_t *c, oidc_cfg_t *base, oidc_cfg_t *add) { @@ -260,7 +272,7 @@ static void oidc_cfg_cache_memcache_merge_server_config(oidc_cfg_t *c, oidc_cfg_ c->cache.memcache_hmax = add->cache.memcache_hmax != OIDC_CONFIG_POS_INT_UNSET ? add->cache.memcache_hmax : base->cache.memcache_hmax; c->cache.memcache_ttl = - add->cache.memcache_ttl != OIDC_CONFIG_POS_INT_UNSET ? add->cache.memcache_ttl : base->cache.memcache_ttl; + add->cache.memcache_ttl != OIDC_CONFIG_POS_TIMEOUT_UNSET ? add->cache.memcache_ttl : base->cache.memcache_ttl; } #endif diff --git a/src/cfg/cache.h b/src/cfg/cache.h index 80f78750..98f4b0ce 100644 --- a/src/cfg/cache.h +++ b/src/cfg/cache.h @@ -92,7 +92,7 @@ OIDC_CFG_MEMBER_FUNCS_DECL(cache_memcache_servers, const char *) OIDC_CFG_MEMBER_FUNCS_DECL(cache_memcache_min, int) OIDC_CFG_MEMBER_FUNCS_DECL(cache_memcache_smax, int) OIDC_CFG_MEMBER_FUNCS_DECL(cache_memcache_hmax, int) -OIDC_CFG_MEMBER_FUNCS_DECL(cache_memcache_ttl, int) +OIDC_CFG_MEMBER_FUNCS_DECL(cache_memcache_ttl, apr_interval_time_t) #endif // USE_MEMCACHE diff --git a/src/cfg/cfg.h b/src/cfg/cfg.h index 8367829d..8e34f987 100644 --- a/src/cfg/cfg.h +++ b/src/cfg/cfg.h @@ -52,6 +52,8 @@ #include "cache/cache.h" #define OIDC_CONFIG_POS_INT_UNSET -1 +/* -1 might be used for unlimited timeout */ +#define OIDC_CONFIG_POS_TIMEOUT_UNSET (apr_interval_time_t)-2 #define OIDCPublicKeyFiles "OIDCPublicKeyFiles" #define OIDCDefaultLoggedOutURL "OIDCDefaultLoggedOutURL" diff --git a/src/cfg/cfg_int.h b/src/cfg/cfg_int.h index 701a1a73..6873ec0b 100644 --- a/src/cfg/cfg_int.h +++ b/src/cfg/cfg_int.h @@ -94,7 +94,7 @@ struct oidc_cfg_cache_t { int memcache_hmax; /* cache_type= memcache: maximum time in microseconds a connection to a memcache server can be idle before being * closed */ - int memcache_ttl; + apr_interval_time_t memcache_ttl; #endif /* diff --git a/src/cfg/parse.c b/src/cfg/parse.c index 5f9c5ce6..6acdb016 100644 --- a/src/cfg/parse.c +++ b/src/cfg/parse.c @@ -196,6 +196,29 @@ const char *oidc_cfg_parse_int_min_max(apr_pool_t *pool, const char *arg, int *i return NULL; } +/* + * parse a timeout string via ap_timeout_parameter_parse into an + * apr_interval_time_t if it is in a valid min/max range + */ +const char *oidc_cfg_parse_timeout_min_max(apr_pool_t *pool, const char *arg, apr_interval_time_t *timeout_value, + apr_interval_time_t min_value, apr_interval_time_t max_value) { + apr_interval_time_t timeout; + + if (ap_timeout_parameter_parse(arg, &timeout, "s") != APR_SUCCESS) { + return apr_psprintf(pool, "not a valid timeout parameter: %s", arg); + } + if (timeout < min_value) { + return apr_psprintf(pool, "timeout value %" APR_TIME_T_FMT " is smaller than the minimum allowed value %" APR_TIME_T_FMT, timeout, + min_value); + } + if (timeout > max_value) { + return apr_psprintf(pool, "timeout value %" APR_TIME_T_FMT " is greater than the maximum allowed value %" APR_TIME_T_FMT, timeout, + max_value); + } + *timeout_value = (int)timeout; + return NULL; +} + /* * check if a string is a valid URL starting with either scheme1 or scheme2 (if not NULL) */ diff --git a/src/cfg/parse.h b/src/cfg/parse.h index 4a046f48..6f3148ea 100644 --- a/src/cfg/parse.h +++ b/src/cfg/parse.h @@ -69,6 +69,8 @@ const char *oidc_cfg_parse_is_valid_encrypted_response_enc(apr_pool_t *pool, con const char *oidc_cfg_parse_boolean(apr_pool_t *pool, const char *arg, int *bool_value); const char *oidc_cfg_parse_int(apr_pool_t *pool, const char *arg, int *int_value); const char *oidc_cfg_parse_int_min_max(apr_pool_t *pool, const char *arg, int *int_value, int min_value, int max_value); +const char *oidc_cfg_parse_timeout_min_max(apr_pool_t *pool, const char *arg, apr_interval_time_t *timeout_value, + apr_interval_time_t min_value, apr_interval_time_t max_value); const char *oidc_cfg_parse_dirname(apr_pool_t *pool, const char *arg, char **value); const char *oidc_cfg_parse_filename(apr_pool_t *pool, const char *arg, char **value); const char *oidc_cfg_parse_relative_or_absolute_url(apr_pool_t *pool, const char *arg, char **value);