Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
- apply exact length matching for at_hash and c_hash validation; for certification purposes
- increase size of the output buffer when using libpcre2 for substitution; closes #915
- bump to 2.4.11.4rc2
- allow setting connection pool parameters for Memcache server connections;
see #916; thanks @rpluem-vf

08/24/2022
- avoid using $< in Makefile
Expand Down
18 changes: 18 additions & 0 deletions auth_openidc.conf
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,24 @@
# Specifies the memcache servers used for caching as a space separated list of <hostname>[:<port>] tuples.
#OIDCMemCacheServers "(<hostname>[:<port>])+"

# Minimum number of connections to each Memcache server per process. Defaults to
# OIDCMemCacheConnectionsHMax.
#OIDCMemCacheConnectionsMin <number>

# All connections above this limit will be closed if they have been idle for
# more than OIDCMemCacheConnectionsTTL. Defaults to OIDCMemCacheConnectionsHMax.
#OIDCMemCacheConnectionsSMax <number>

# Maximum number of connections to each Memcache server per process. Defaults to
# ThreadsPerChild or if mod_http2 is loaded to ThreadsPerChild - 1 + H2MaxWorkers.
#OIDCMemCacheConnectionsHMax <number>

# Maximum time in seconds a connection to a Memcache server can be idle before
# being closed. Defaults to 60 seconds.
# Only for Apache >= 2.4.x: By adding a postfix of ms, the timeout can be also
# set in milliseconds. Defaults to 60 seconds.
#OIDCMemCacheConnectionsTTL <seconds>

# Required if Redis support is compiled in and when using OIDCCacheType "redis":
# Specifies the Redis server used for caching as a <hostname>[:<port>] tuple.
#OIDCRedisCacheServer <hostname>[:<port>]
Expand Down
63 changes: 61 additions & 2 deletions src/cache/memcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,23 @@

#include "mod_auth_openidc.h"
#include <apr_memcache.h>
#include <apr_optional.h>
#include <ap_mpm.h>

extern module AP_MODULE_DECLARE_DATA auth_openidc_module;


#if AP_MODULE_MAGIC_AT_LEAST(20120211, 125)
#include <mod_http2.h>
#else
/*
* Copy and paste from mod_http2.h where mod_http2.h is not available
*/
APR_DECLARE_OPTIONAL_FN(void,
http2_get_num_workers, (server_rec *s,
int *minw, int *max));
#endif

typedef struct oidc_cache_cfg_memcache_t {
/* cache_type = memcache: memcache ptr */
apr_memcache_t *cache_memcache;
Expand Down Expand Up @@ -79,6 +93,9 @@ static int oidc_cache_memcache_post_config(server_rec *s) {
char* split;
char* tok;
apr_pool_t *p = s->process->pool;
APR_OPTIONAL_FN_TYPE(http2_get_num_workers) *get_h2_num_workers;
int max_threads, minw, maxw;
apr_uint32_t min, smax, hmax, ttl;

if (cfg->cache_memcache_servers == NULL) {
oidc_serror(s,
Expand All @@ -102,6 +119,49 @@ static int oidc_cache_memcache_post_config(server_rec *s) {
return HTTP_INTERNAL_SERVER_ERROR;
}

/*
* When mod_http2 is loaded we might have more threads since it has
* its own pool of processing threads.
*/
ap_mpm_query(AP_MPMQ_MAX_THREADS, &max_threads);
get_h2_num_workers = APR_RETRIEVE_OPTIONAL_FN(http2_get_num_workers);
if (get_h2_num_workers) {
get_h2_num_workers(s, &minw, &maxw);
/* So now the max is:
* max_threads-1 threads for HTTP/1 each requiring one connection
* + one thread for HTTP/2 requiring maxw connections
*/
max_threads = max_threads - 1 + maxw;
}
min = cfg->cache_memcache_min;
smax = cfg->cache_memcache_smax;
hmax = cfg->cache_memcache_hmax;
ttl = cfg->cache_memcache_ttl;
if (max_threads > 0 && hmax == 0) {
hmax = max_threads;
if (smax == 0) {
smax = hmax;
}
if (min == 0) {
min = hmax;
}
} else {
if (hmax == 0) {
hmax = 1;
}
if (smax == 0) {
smax = 1;
}
}
if (ttl == 0) {
ttl = apr_time_from_sec(60);
}
if (smax > hmax) {
smax = hmax;
}
if (min > smax) {
min = smax;
}
/* loop again over the provided servers */
cache_config = apr_pstrdup(p, cfg->cache_memcache_servers);
split = apr_strtok(cache_config, OIDC_STR_SPACE, &tok);
Expand Down Expand Up @@ -129,8 +189,7 @@ static int oidc_cache_memcache_post_config(server_rec *s) {
port = 11211;

/* create the memcache server struct */
// TODO: tune this
rv = apr_memcache_server_create(p, host_str, port, 0, 1, 1, 60, &st);
rv = apr_memcache_server_create(p, host_str, port, min, smax, hmax, ttl, &st);
if (rv != APR_SUCCESS) {
oidc_serror(s, "failed to create cache server: %s:%d", host_str,
port);
Expand Down
96 changes: 96 additions & 0 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,66 @@ static const char* oidc_set_int_slot(cmd_parms *cmd, void *struct_ptr,
return ap_set_int_slot(cmd, cfg, arg);
}

/*
* set an apr_uint32_t value in the server config
*/
static const char* oidc_set_uint32_slot(cmd_parms *cmd, void *struct_ptr,
const char *arg) {
char *endptr;
apr_int64_t value;
oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
&auth_openidc_module);
apr_uintptr_t offset = (apr_uintptr_t)cmd->info;

value = apr_strtoi64(arg, &endptr, 10);
if (errno != 0 || *endptr != '\0') {
return OIDC_CONFIG_DIR_RV(cmd, arg);
}
if (value > APR_UINT32_MAX || value < 0) {
return OIDC_CONFIG_DIR_RV(cmd, "Value out of range");
}
*(apr_uint32_t *)((char *)cfg + offset) = (apr_uint32_t)value;
return NULL;
}

/*
* set an 32 bit uint timeout slot in the server config
*/
static const char* oidc_set_timeout_slot(cmd_parms *cmd, void *struct_ptr,
const char *arg) {
#if AP_MODULE_MAGIC_AT_LEAST(20080920, 2)
apr_status_t rv;
apr_interval_time_t timeout;
#else
char *endptr;
apr_int64_t timeout;
#endif
oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
&auth_openidc_module);
apr_uintptr_t offset = (apr_uintptr_t)cmd->info;

#if AP_MODULE_MAGIC_AT_LEAST(20080920, 2)
rv = ap_timeout_parameter_parse(arg, &timeout, "s");
if (rv != APR_SUCCESS) {
return OIDC_CONFIG_DIR_RV(cmd, arg);
}
#else
timeout = apr_strtoi64(arg, &endptr, 10);
if (errno != 0 || *endptr != '\0') {
return OIDC_CONFIG_DIR_RV(cmd, arg);
}
if (timeout > apr_time_sec(APR_INT64_MAX)) {
return OIDC_CONFIG_DIR_RV(cmd, "Value out of range");
}
timeout = apr_time_from_sec(timeout);
#endif
if (timeout > APR_UINT32_MAX) {
return OIDC_CONFIG_DIR_RV(cmd, "Value out of range");
}
*(apr_uint32_t *)((char *)cfg + offset) = (apr_uint32_t)timeout;
return NULL;
}

/*
* set a URL value in a config record
*/
Expand Down Expand Up @@ -1442,6 +1502,10 @@ void* oidc_create_server_config(apr_pool_t *pool, server_rec *svr) {
c->cache_file_clean_interval = OIDC_DEFAULT_CACHE_FILE_CLEAN_INTERVAL;
#ifdef USE_MEMCACHE
c->cache_memcache_servers = NULL;
c->cache_memcache_min = 0;
c->cache_memcache_smax = 0;
c->cache_memcache_hmax = 0;
c->cache_memcache_ttl = 0;
#endif
c->cache_shm_size_max = OIDC_DEFAULT_CACHE_SHM_SIZE;
c->cache_shm_entry_size_max = OIDC_DEFAULT_CACHE_SHM_ENTRY_SIZE_MAX;
Expand Down Expand Up @@ -1856,6 +1920,18 @@ void* oidc_merge_server_config(apr_pool_t *pool, void *BASE, void *ADD) {
c->cache_memcache_servers =
add->cache_memcache_servers != NULL ?
add->cache_memcache_servers : base->cache_memcache_servers;
c->cache_memcache_min =
add->cache_memcache_min ?
add->cache_memcache_min : base->cache_memcache_min;
c->cache_memcache_smax =
add->cache_memcache_smax ?
add->cache_memcache_smax : base->cache_memcache_smax;
c->cache_memcache_hmax =
add->cache_memcache_hmax ?
add->cache_memcache_hmax : base->cache_memcache_hmax;
c->cache_memcache_ttl =
add->cache_memcache_ttl ?
add->cache_memcache_ttl : base->cache_memcache_ttl;
#endif
c->cache_shm_size_max =
add->cache_shm_size_max != OIDC_DEFAULT_CACHE_SHM_SIZE ?
Expand Down Expand Up @@ -3353,6 +3429,26 @@ const command_rec oidc_config_cmds[] = {
(void*)APR_OFFSETOF(oidc_cfg, cache_memcache_servers),
RSRC_CONF,
"Memcache servers used for caching (space separated list of <hostname>[:<port>] tuples)"),
AP_INIT_TAKE1(OIDCMemCacheConnectionsMin,
oidc_set_uint32_slot,
(void*)APR_OFFSETOF(oidc_cfg, cache_memcache_min),
RSRC_CONF,
"Minimum number of connections to each Memcache server per process"),
AP_INIT_TAKE1(OIDCMemCacheConnectionsSMax,
oidc_set_uint32_slot,
(void*)APR_OFFSETOF(oidc_cfg, cache_memcache_smax),
RSRC_CONF,
"Soft maximum number of connections to each Memcache server per process"),
AP_INIT_TAKE1(OIDCMemCacheConnectionsHMax,
oidc_set_uint32_slot,
(void*)APR_OFFSETOF(oidc_cfg, cache_memcache_hmax),
RSRC_CONF,
"Hard maximum number of connections to each Memcache server per process"),
AP_INIT_TAKE1(OIDCMemCacheConnectionsTTL,
oidc_set_timeout_slot,
(void*)APR_OFFSETOF(oidc_cfg, cache_memcache_ttl),
RSRC_CONF,
"Maximum time in seconds a connection to a Memcache server can be idle before being closed"),
#endif
AP_INIT_TAKE1(OIDCCacheShmMax,
oidc_set_int_slot,
Expand Down
12 changes: 12 additions & 0 deletions src/mod_auth_openidc.h
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,14 @@ typedef struct oidc_cfg {
#ifdef USE_MEMCACHE
/* cache_type= memcache: list of memcache host/port servers to use */
char *cache_memcache_servers;
/* cache_type= memcache: minimum number of connections to each memcache server per process*/
apr_uint32_t cache_memcache_min;
/* cache_type= memcache: soft maximum number of connections to each memcache server per process */
apr_uint32_t cache_memcache_smax;
/* cache_type= memcache: hard maximum number of connections to each memcache server per process */
apr_uint32_t cache_memcache_hmax;
/* cache_type= memcache: maximum time in microseconds a connection to a memcache server can be idle before being closed */
apr_uint32_t cache_memcache_ttl;
#endif
/* cache_type = shm: size of the shared memory segment (cq. max number of cached entries) */
int cache_shm_size_max;
Expand Down Expand Up @@ -725,6 +733,10 @@ int oidc_oauth_return_www_authenticate(request_rec *r, const char *error, const
#define OIDCOAuthRemoteUserClaim "OIDCOAuthRemoteUserClaim"
#define OIDCSessionType "OIDCSessionType"
#define OIDCMemCacheServers "OIDCMemCacheServers"
#define OIDCMemCacheConnectionsMin "OIDCMemCacheConnectionsMin"
#define OIDCMemCacheConnectionsSMax "OIDCMemCacheConnectionsSMax"
#define OIDCMemCacheConnectionsHMax "OIDCMemCacheConnectionsHMax"
#define OIDCMemCacheConnectionsTTL "OIDCMemCacheConnectionsTTL"
#define OIDCCacheShmMax "OIDCCacheShmMax"
#define OIDCCacheShmEntrySizeMax "OIDCCacheShmEntrySizeMax"
#define OIDCRedisCacheServer "OIDCRedisCacheServer"
Expand Down
15 changes: 15 additions & 0 deletions test/stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,21 @@ AP_DECLARE(void) ap_log_error_(const char *file, int line, int module_index,
return NULL;
}

AP_DECLARE(apr_status_t) ap_mpm_query(int query_code, int *result) {
*result = 1;
return APR_SUCCESS;
}

#if AP_MODULE_MAGIC_AT_LEAST(20080920, 2)
AP_DECLARE(apr_status_t) ap_timeout_parameter_parse(
const char *timeout_parameter,
apr_interval_time_t *timeout,
const char *default_time_unit) {
*timeout = 0;
return APR_SUCCESS;
}
#endif

#if MODULE_MAGIC_NUMBER_MAJOR >= 20100714
AP_DECLARE(int) ap_expr_exec(request_rec *r, const ap_expr_info_t *expr,
const char **err) {
Expand Down