79
79
/* represents one (fixed size) cache entry, cq. name/value string pair */
80
80
typedef struct oidc_cache_shm_entry_t {
81
81
/* name of the cache entry */
82
char key[OIDC_CACHE_SHM_KEY_MAX];
82
char section_key[OIDC_CACHE_SHM_KEY_MAX];
83
83
/* value of the cache entry */
84
84
char value[OIDC_CACHE_SHM_VALUE_MAX];
85
85
/* last (read) access timestamp */
91
91
/* create the cache context */
92
92
static void *oidc_cache_shm_cfg_create(apr_pool_t *pool) {
93
oidc_cache_cfg_shm_t *context = apr_pcalloc(pool, sizeof(oidc_cache_cfg_shm_t));
93
oidc_cache_cfg_shm_t *context = apr_pcalloc(pool,
94
sizeof(oidc_cache_cfg_shm_t));
94
95
context->mutex_filename = NULL;
95
96
context->shm = NULL;
96
97
context->mutex = NULL;
104
105
oidc_cfg *cfg = (oidc_cfg *) ap_get_module_config(s->module_config,
105
106
&auth_openidc_module);
107
if (cfg->cache_cfg != NULL) return APR_SUCCESS;
108
if (cfg->cache_cfg != NULL)
108
110
oidc_cache_cfg_shm_t *context = oidc_cache_shm_cfg_create(s->process->pool);
109
111
cfg->cache_cfg = context;
113
115
sizeof(oidc_cache_shm_entry_t) * cfg->cache_shm_size_max,
114
116
NULL, s->process->pool);
115
117
if (rv != APR_SUCCESS) {
116
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
117
"oidc_cache_shm_post_config: apr_shm_create failed to create shared memory segment");
118
oidc_serror(s, "apr_shm_create failed to create shared memory segment");
118
119
return HTTP_INTERNAL_SERVER_ERROR;
137
138
(const char *) context->mutex_filename, APR_LOCK_DEFAULT,
138
139
s->process->pool);
139
140
if (rv != APR_SUCCESS) {
140
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
141
"oidc_cache_shm_post_config: apr_global_mutex_create failed to create mutex on file %s",
142
"apr_global_mutex_create failed to create mutex on file %s",
142
143
context->mutex_filename);
143
144
return HTTP_INTERNAL_SERVER_ERROR;
151
152
rv = unixd_set_global_mutex_perms(context->mutex);
153
154
if (rv != APR_SUCCESS) {
154
ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
155
"oidc_cache_shm_post_config: unixd_set_global_mutex_perms failed; could not set permissions ");
156
"unixd_set_global_mutex_perms failed; could not set permissions ");
156
157
return HTTP_INTERNAL_SERVER_ERROR;
164
165
* initialize the shared memory segment in a child process
166
167
int oidc_cache_shm_child_init(apr_pool_t *p, server_rec *s) {
167
oidc_cfg *cfg = ap_get_module_config(s->module_config, &auth_openidc_module);
168
oidc_cache_cfg_shm_t *context = (oidc_cache_cfg_shm_t *)cfg->cache_cfg;
168
oidc_cfg *cfg = ap_get_module_config(s->module_config,
169
&auth_openidc_module);
170
oidc_cache_cfg_shm_t *context = (oidc_cache_cfg_shm_t *) cfg->cache_cfg;
170
172
/* initialize the lock for the child process */
171
173
apr_status_t rv = apr_global_mutex_child_init(&context->mutex,
172
174
(const char *) context->mutex_filename, p);
174
176
if (rv != APR_SUCCESS) {
175
ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
176
"oic_cache_shm_child_init: apr_global_mutex_child_init failed to reopen mutex on file %s",
178
"apr_global_mutex_child_init failed to reopen mutex on file %s",
177
179
context->mutex_filename);
186
* assemble single key name based on section/key input
188
static char *oidc_cache_shm_get_key(apr_pool_t *pool, const char *section,
190
return apr_psprintf(pool, "%s:%s", section, key);
184
194
* get a value from the shared memory cache
186
static apr_byte_t oidc_cache_shm_get(request_rec *r, const char *key,
187
const char **value) {
196
static apr_byte_t oidc_cache_shm_get(request_rec *r, const char *section,
197
const char *key, const char **value) {
189
ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
190
"oidc_cache_shm_get: entering \"%s\"", key);
199
oidc_debug(r, "enter, section=\"%s\", key=\"%s\"", section, key);
192
201
oidc_cfg *cfg = ap_get_module_config(r->server->module_config,
193
202
&auth_openidc_module);
194
oidc_cache_cfg_shm_t *context = (oidc_cache_cfg_shm_t *)cfg->cache_cfg;
203
oidc_cache_cfg_shm_t *context = (oidc_cache_cfg_shm_t *) cfg->cache_cfg;
207
const char *section_key = oidc_cache_shm_get_key(r->pool, section, key);
200
211
/* grab the global lock */
201
212
if ((rv = apr_global_mutex_lock(context->mutex)) != APR_SUCCESS) {
202
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
203
"oidc_cache_shm_get: apr_global_mutex_lock() failed [%d]", rv);
213
oidc_error(r, "apr_global_mutex_lock() failed [%d]", rv);
210
220
/* loop over the block, looking for the key */
211
221
for (i = 0; i < cfg->cache_shm_size_max; i++) {
212
const char *tablekey = table[i].key;
222
const char *tablekey = table[i].section_key;
214
224
if (tablekey == NULL)
217
if (strcmp(tablekey, key) == 0) {
227
if (apr_strnatcmp(tablekey, section_key) == 0) {
219
229
/* found a match, check if it has expired */
220
230
if (table[i].expires > apr_time_now()) {
236
246
* store a value in the shared memory cache
238
static apr_byte_t oidc_cache_shm_set(request_rec *r, const char *key,
239
const char *value, apr_time_t expiry) {
248
static apr_byte_t oidc_cache_shm_set(request_rec *r, const char *section,
249
const char *key, const char *value, apr_time_t expiry) {
251
oidc_debug(r, "enter, section=\"%s\", key=\"%s\", value size=%llu", section,
252
key, value ? (unsigned long long )strlen(value) : 0);
241
254
oidc_cfg *cfg = ap_get_module_config(r->server->module_config,
242
255
&auth_openidc_module);
243
oidc_cache_cfg_shm_t *context = (oidc_cache_cfg_shm_t *)cfg->cache_cfg;
245
ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
246
"oidc_cache_shm_set: entering \"%s\" (value size=(%zu)", key,
247
value ? strlen(value) : 0);
256
oidc_cache_cfg_shm_t *context = (oidc_cache_cfg_shm_t *) cfg->cache_cfg;
249
258
oidc_cache_shm_entry_t *match, *free, *lru;
250
259
oidc_cache_shm_entry_t *table;
264
const char *section_key = oidc_cache_shm_get_key(r->pool, section, key);
255
266
/* check that the passed in key is valid */
256
if (key == NULL || strlen(key) > OIDC_CACHE_SHM_KEY_MAX) {
257
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
258
"oidc_cache_shm_set: could not set value since key is NULL or too long (%s)",
267
if (strlen(section_key) > OIDC_CACHE_SHM_KEY_MAX) {
268
oidc_error(r, "could not set value since key is too long (%s)",
263
273
/* check that the passed in value is valid */
264
if ( (value != NULL) && strlen(value) > OIDC_CACHE_SHM_VALUE_MAX) {
265
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
266
"oidc_cache_shm_set: could not set value since value is too long (%zu > %d)",
274
if ((value != NULL) && strlen(value) > OIDC_CACHE_SHM_VALUE_MAX) {
275
oidc_error(r, "could not set value since value is too long (%zu > %d)",
267
276
strlen(value), OIDC_CACHE_SHM_VALUE_MAX);
271
280
/* grab the global lock */
272
281
if (apr_global_mutex_lock(context->mutex) != APR_SUCCESS) {
273
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
274
"oidc_cache_shm_set: apr_global_mutex_lock() failed");
282
oidc_error(r, "apr_global_mutex_lock() failed");
288
296
for (i = 0; i < cfg->cache_shm_size_max; i++) {
290
298
/* see if this slot is free */
291
if (table[i].key[0] == '\0') {
292
if (free == NULL) free = &table[i];
299
if (table[i].section_key[0] == '\0') {
296
305
/* see if a value already exists for this key */
297
if (strcmp(table[i].key, key) == 0) {
306
if (apr_strnatcmp(table[i].section_key, section_key) == 0) {
298
307
match = &table[i];
302
311
/* see if this slot has expired */
303
312
if (table[i].expires <= current_time) {
304
if (free == NULL) free = &table[i];
316
326
if (match == NULL && free == NULL) {
317
327
age = (current_time - lru->access) / 1000000;
318
328
if (age < 3600) {
319
ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r,
320
"oidc_cache_shm_set: dropping LRU entry with age = %" APR_TIME_T_FMT "s, which is less than one hour; consider increasing the shared memory caching space (which is %d now) with the (global) OIDCCacheShmMax setting.",
330
"dropping LRU entry with age = %" APR_TIME_T_FMT "s, which is less than one hour; consider increasing the shared memory caching space (which is %d now) with the (global) OIDCCacheShmMax setting.",
321
331
age, cfg->cache_shm_size_max);
327
337
if (value != NULL) {
329
339
/* fill out the entry with the provided data */
340
strcpy(t->section_key, section_key);
331
341
strcpy(t->value, value);
332
342
t->expires = expiry;
333
343
t->access = current_time;
347
t->section_key[0] = '\0';
340
350
/* release the global lock */
346
356
static int oidc_cache_shm_destroy(server_rec *s) {
347
oidc_cfg *cfg = (oidc_cfg *) ap_get_module_config(
348
s->module_config, &auth_openidc_module);
349
oidc_cache_cfg_shm_t *context = (oidc_cache_cfg_shm_t *)cfg->cache_cfg;
357
oidc_cfg *cfg = (oidc_cfg *) ap_get_module_config(s->module_config,
358
&auth_openidc_module);
359
oidc_cache_cfg_shm_t *context = (oidc_cache_cfg_shm_t *) cfg->cache_cfg;
350
360
apr_status_t rv = APR_SUCCESS;
353
rv = apr_shm_destroy(context->shm);
354
ap_log_error(APLOG_MARK, OIDC_DEBUG, rv, s,
355
"oidc_cache_shm_destroy: apr_shm_destroy returned: %d", rv);
363
rv = apr_shm_destroy(context->shm);
364
oidc_sdebug(s, "apr_shm_destroy returned: %d", rv);
359
if (context->mutex) {
360
rv = apr_global_mutex_destroy(context->mutex);
361
ap_log_error(APLOG_MARK, OIDC_DEBUG, rv, s,
362
"oidc_cache_shm_destroy: apr_global_mutex_destroy returned: %d", rv);
363
context->mutex = NULL;
368
if (context->mutex) {
369
rv = apr_global_mutex_destroy(context->mutex);
370
oidc_sdebug(s, "apr_global_mutex_destroy returned: %d", rv);
371
context->mutex = NULL;