93
93
* return the cache file name for a specified key
95
static const char *oidc_cache_file_name(request_rec *r, const char *key) {
96
return apr_psprintf(r->pool, "%s%s", OIDC_CACHE_FILE_PREFIX, key);
95
static const char *oidc_cache_file_name(request_rec *r, const char *section,
97
return apr_psprintf(r->pool, "%s%s-%s", OIDC_CACHE_FILE_PREFIX, section,
100
102
* return the fully qualified path name to a cache file for a specified key
102
static const char *oidc_cache_file_path(request_rec *r, const char *key) {
104
static const char *oidc_cache_file_path(request_rec *r, const char *section,
103
106
oidc_cfg *cfg = ap_get_module_config(r->server->module_config,
104
107
&auth_openidc_module);
105
108
return apr_psprintf(r->pool, "%s/%s", cfg->cache_file_dir,
106
oidc_cache_file_name(r, key));
109
oidc_cache_file_name(r, section, key));
122
125
/* test for system errors */
123
126
if (rc != APR_SUCCESS) {
124
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
125
"oidc_cache_file_read: could not read from: %s (%s)", path,
127
oidc_error(r, "could not read from: %s (%s)", path,
126
128
apr_strerror(rc, s_err, sizeof(s_err)));
129
131
/* ensure that we've got the requested number of bytes */
130
132
if (bytes_read != len) {
131
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
132
"oidc_cache_file_read: could not read enough bytes from: \"%s\", bytes_read (%" APR_SIZE_T_FMT ") != len (%" APR_SIZE_T_FMT ")",
134
"could not read enough bytes from: \"%s\", bytes_read (%" APR_SIZE_T_FMT ") != len (%" APR_SIZE_T_FMT ")",
133
135
path, bytes_read, len);
134
136
rc = APR_EGENERAL;
153
155
/* check for a system error */
154
156
if (rc != APR_SUCCESS) {
155
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
156
"oidc_cache_file_write: could not write to: \"%s\" (%s)", path,
157
oidc_error(r, "could not write to: \"%s\" (%s)", path,
157
158
apr_strerror(rc, s_err, sizeof(s_err)));
161
162
/* check that all bytes from the header were written */
162
163
if (bytes_written != len) {
163
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
164
"oidc_cache_file_write: could not write enough bytes to: \"%s\", bytes_written (%" APR_SIZE_T_FMT ") != len (%" APR_SIZE_T_FMT ")",
165
"could not write enough bytes to: \"%s\", bytes_written (%" APR_SIZE_T_FMT ") != len (%" APR_SIZE_T_FMT ")",
165
166
path, bytes_written, len);
166
167
return APR_EGENERAL;
173
174
* get a value for the specified key from the cache
175
static apr_byte_t oidc_cache_file_get(request_rec *r, const char *key,
176
const char **value) {
176
static apr_byte_t oidc_cache_file_get(request_rec *r, const char *section,
177
const char *key, const char **value) {
177
178
apr_file_t *fd = NULL;
178
179
apr_status_t rc = APR_SUCCESS;
181
182
/* get the fully qualified path to the cache file based on the key name */
182
const char *path = oidc_cache_file_path(r, key);
183
const char *path = oidc_cache_file_path(r, section, key);
184
185
/* open the cache file if it exists, otherwise we just have a "regular" cache miss */
185
186
if (apr_file_open(&fd, path, APR_FOPEN_READ | APR_FOPEN_BUFFERED,
186
187
APR_OS_DEFAULT, r->pool) != APR_SUCCESS) {
187
ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
188
"oidc_cache_file_get: cache miss for key \"%s\"", key);
188
oidc_debug(r, "cache miss for key \"%s\"", key);
210
210
apr_file_close(fd);
212
212
/* log this event */
213
ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
214
"oidc_cache_file_get: cache entry \"%s\" expired, removing file \"%s\"",
213
oidc_debug(r, "cache entry \"%s\" expired, removing file \"%s\"", key,
217
216
/* and kill it */
218
217
if ((rc = apr_file_remove(path, r->pool)) != APR_SUCCESS) {
219
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
220
"oidc_cache_file_get: could not delete cache file \"%s\" (%s)",
221
path, apr_strerror(rc, s_err, sizeof(s_err)));
218
oidc_error(r, "could not delete cache file \"%s\" (%s)", path,
219
apr_strerror(rc, s_err, sizeof(s_err)));
224
222
/* nothing strange happened really */
234
232
/* barf on failure */
235
233
if (rc != APR_SUCCESS) {
236
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
237
"oidc_cache_file_get: could not read cache value from \"%s\"",
234
oidc_error(r, "could not read cache value from \"%s\"", path);
239
235
goto error_close;
244
240
apr_file_close(fd);
246
242
/* log a successful cache hit */
247
ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
248
"oidc_cache_file_get: cache hit for key \"%s\" (%" APR_SIZE_T_FMT " bytes, expiring in: %" APR_TIME_T_FMT ")",
244
"cache hit for key \"%s\" (%" APR_SIZE_T_FMT " bytes, expiring in: %" APR_TIME_T_FMT ")",
249
245
key, info.len, apr_time_sec(info.expire - apr_time_now()));
255
251
apr_file_unlock(fd);
256
252
apr_file_close(fd);
258
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
259
"oidc_cache_file_get: return error status %d (%s)", rc,
254
oidc_error(r, "return error status %d (%s)", rc,
260
255
apr_strerror(rc, s_err, sizeof(s_err)));
281
276
&auth_openidc_module);
283
278
/* get the path to the metadata file that holds "last cleaned" metadata info */
284
const char *metadata_path = oidc_cache_file_path(r,
285
OIDC_CACHE_FILE_LAST_CLEANED);
279
const char *metadata_path = oidc_cache_file_path(r, "cache-file",
280
OIDC_CACHE_FILE_LAST_CLEANED);
287
282
/* open the metadata file if it exists */
288
283
if ((rc = apr_stat(&fi, metadata_path, APR_FINFO_MTIME, r->pool))
291
286
/* really only clean once per so much time, check that we haven not recently run */
292
287
if (apr_time_now() < fi.mtime + apr_time_from_sec(cfg->cache_file_clean_interval)) {
293
ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
294
"oidc_cache_clean: last cleanup call was less than %d seconds ago (next one as early as in %" APR_TIME_T_FMT " secs)",
289
"last cleanup call was less than %d seconds ago (next one as early as in %" APR_TIME_T_FMT " secs)",
295
290
cfg->cache_file_clean_interval,
297
fi.mtime + apr_time_from_sec(cfg->cache_file_clean_interval) - apr_time_now()));
291
apr_time_sec( fi.mtime + apr_time_from_sec(cfg->cache_file_clean_interval) - apr_time_now()));
298
292
return APR_SUCCESS;
307
301
if ((rc = apr_file_open(&fd, metadata_path,
308
302
(APR_FOPEN_WRITE | APR_FOPEN_CREATE), APR_OS_DEFAULT, r->pool))
309
303
!= APR_SUCCESS) {
310
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
311
"oidc_cache_file_clean: error creating cache timestamp file '%s' (%s)",
304
oidc_error(r, "error creating cache timestamp file '%s' (%s)",
312
305
metadata_path, apr_strerror(rc, s_err, sizeof(s_err)));
316
309
/* and cleanup... */
317
310
if ((rc = apr_file_close(fd)) != APR_SUCCESS) {
318
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
319
"oidc_cache_file_clean: error closing cache timestamp file '%s' (%s)",
311
oidc_error(r, "error closing cache timestamp file '%s' (%s)",
320
312
metadata_path, apr_strerror(rc, s_err, sizeof(s_err)));
324
316
/* time to clean, open the cache directory */
325
317
if ((rc = apr_dir_open(&dir, cfg->cache_file_dir, r->pool)) != APR_SUCCESS) {
326
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
327
"oidc_cache_file_clean: error opening cache directory '%s' for cleaning (%s)",
318
oidc_error(r, "error opening cache directory '%s' for cleaning (%s)",
328
319
cfg->cache_file_dir, apr_strerror(rc, s_err, sizeof(s_err)));
340
331
/* skip non-cache entries, cq. the ".", ".." and the metadata file */
341
332
if ((fi.name[0] == '.')
342
333
|| (strstr(fi.name, OIDC_CACHE_FILE_PREFIX) != fi.name)
343
|| ((apr_strnatcmp(fi.name, oidc_cache_file_name(r,
344
OIDC_CACHE_FILE_LAST_CLEANED)) == 0)))
334
|| ((apr_strnatcmp(fi.name,
335
oidc_cache_file_name(r, "cache-file",
336
OIDC_CACHE_FILE_LAST_CLEANED)) == 0)))
347
339
/* get the fully qualified path to the cache file and open it */
349
341
cfg->cache_file_dir, fi.name);
350
342
if ((rc = apr_file_open(&fd, path, APR_FOPEN_READ, APR_OS_DEFAULT,
351
343
r->pool)) != APR_SUCCESS) {
352
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
353
"oidc_cache_file_clean: unable to open cache entry \"%s\" (%s)",
354
path, apr_strerror(rc, s_err, sizeof(s_err)));
344
oidc_error(r, "unable to open cache entry \"%s\" (%s)", path,
345
apr_strerror(rc, s_err, sizeof(s_err)));
369
360
/* the cache entry expired, we're going to remove it so log that event */
370
ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
371
"oidc_cache_file_clean: cache entry (%s) expired, removing file \"%s\")",
361
oidc_debug(r, "cache entry (%s) expired, removing file \"%s\")",
376
366
/* file open returned an error, log that */
377
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
378
"oidc_cache_file_clean: cache entry (%s) corrupted (%s), removing file \"%s\"",
368
"cache entry (%s) corrupted (%s), removing file \"%s\"",
379
369
fi.name, apr_strerror(rc, s_err, sizeof(s_err)), path);
384
374
if ((rc = apr_file_remove(path, r->pool)) != APR_SUCCESS) {
386
376
/* hrm, this will most probably happen again on the next run... */
387
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
388
"oidc_cache_file_clean: could not delete cache file \"%s\" (%s)",
389
path, apr_strerror(rc, s_err, sizeof(s_err)));
377
oidc_error(r, "could not delete cache file \"%s\" (%s)", path,
378
apr_strerror(rc, s_err, sizeof(s_err)));
402
391
* write a value for the specified key to the cache
404
static apr_byte_t oidc_cache_file_set(request_rec *r, const char *key,
405
const char *value, apr_time_t expiry) {
393
static apr_byte_t oidc_cache_file_set(request_rec *r, const char *section,
394
const char *key, const char *value, apr_time_t expiry) {
406
395
apr_file_t *fd = NULL;
407
396
apr_status_t rc = APR_SUCCESS;
410
399
/* get the fully qualified path to the cache file based on the key name */
411
const char *path = oidc_cache_file_path(r, key);
400
const char *path = oidc_cache_file_path(r, section, key);
413
402
/* only on writes (not on reads) we clean the cache first (if not done recently) */
414
403
oidc_cache_file_clean(r);
416
405
/* just remove cache file if value is NULL */
417
406
if (value == NULL) {
418
407
if ((rc = apr_file_remove(path, r->pool)) != APR_SUCCESS) {
419
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
420
"oidc_cache_file_set: could not delete cache file \"%s\" (%s)",
421
path, apr_strerror(rc, s_err, sizeof(s_err)));
408
oidc_error(r, "could not delete cache file \"%s\" (%s)", path,
409
apr_strerror(rc, s_err, sizeof(s_err)));
426
414
/* try to open the cache file for writing, creating it if it does not exist */
427
415
if ((rc = apr_file_open(&fd, path, (APR_FOPEN_WRITE | APR_FOPEN_CREATE),
428
416
APR_OS_DEFAULT, r->pool)) != APR_SUCCESS) {
429
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
430
"oidc_cache_file_set: cache file \"%s\" could not be opened (%s)",
431
path, apr_strerror(rc, s_err, sizeof(s_err)));
417
oidc_error(r, "cache file \"%s\" could not be opened (%s)", path,
418
apr_strerror(rc, s_err, sizeof(s_err)));
457
444
apr_file_close(fd);
459
446
/* log our success */
460
ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r,
461
"oidc_cache_file_set: set entry for key \"%s\" (%" APR_SIZE_T_FMT " bytes, expires in: %" APR_TIME_T_FMT ")",
448
"set entry for key \"%s\" (%" APR_SIZE_T_FMT " bytes, expires in: %" APR_TIME_T_FMT ")",
462
449
key, info.len, apr_time_sec(expiry - apr_time_now()));