Commit 369393fa authored by Moritz Schlarb's avatar Moritz Schlarb

Merge tag 'upstream/2.3.1'

Upstream version 2.3.1
parents d0245df2 31d78a71
......@@ -5,6 +5,7 @@ The primary author of mod_auth_openidc is:
Thanks to the following people for contributing to mod_auth_openidc by
reporting bugs, providing fixes, suggesting useful features or other:
Dániel SÜTTŐ <https://github.com/suttod>
Roland Hedberg <https://github.com/rohe>
Bill Simon <https://github.com/billsimon>
Jim Fox <https://github.com/jimfox>
......@@ -33,3 +34,5 @@ reporting bugs, providing fixes, suggesting useful features or other:
drdivano <https://github.com/drdivano>
AliceWonderMiscreations <https://github.com/AliceWonderMiscreations>
Wouter Hund <https://github.com/wouterhund>
Hans Keeler <https://github.com/hkeeler>
Moritz Schlarb <https://github.com/moschlar>
07/19/2017
- handle multiple values in X-Forwarded-* headers as to better support chains of reverse proxies in front of mod_auth_openidc
- log request headers in oidc_util_hdr_in_get
- release 2.3.1
07/13/2017
- remove A128GCM/A192GCM from the supported algorithms in docs/auth_openidc.conf
because cjose doesn't support A128GCM and A192GCM (yet)
- bump to 2.3.1rc5
07/09/2017
- refactor oidc_get_current_url_port so that it assumes the default port when
X-Forwarded-Proto has been set; closes #282 and may address #278
- bump to 2.3.1rc4
07/07/2017
- use the defined name (`Provided-Token-Binding-ID`) for the provided token binding ID HTTP header
see: https://tools.ietf.org/html/draft-campbell-tokbind-ttrp-00#section-2.1
depends on mod_token_binding >= 0.3.0 now
- bump to 2.3.1rc3
06/29/2017
- support sending the authentication request via HTTP POST through HTML/Javascript autosubmit
- bump to 2.3.1rc2
06/28/2017
- support private_key_jwt and client_secret_jwt as client authentication methods for token introspection
- bump to 2.3.1rc1
06/22/2017
- fix bug where token_endpoint_auth set to private_key_jwt would fail to provide the credential if client_secret wasn't set
- bump to 2.3.1rc0
06/13/2017
- release 2.3.0
06/07/2017
- fix file cache backend: allow caching of non-filename friendly keys such as configuration URLs and JWKs URIs
- enable JQ-based claims expression matching when compiled from source with --with-jq=<dir>, e.g.:
Require claims_expr '.aud == "ac_oic_client" and (.scope | index("profile") != null)'
- normalize cache backend logging
- bump to 2.3.0rc3
06/06/2017
- avoid cleaning our own state cookie twice when it is expired
- bump to 2.3.0rc2
06/02/2017
- refactor remote user handling so it allows for postfixing with the issuer value after applying the regex
- bump to 2.3.0rc1
05/31/2017
- add support for custom actions to take after authorization fails with OIDCUnAutzAction
this enables stepup authentication scenarios when combined with the following:
- add OIDCPathAuthRequestParams that is configurable on a per-path basis and use OIDCAuthRequestParams for the static per-provider value
- add OIDCPathScope that is configurable on a per-path basis and concatenate with OIDCScope as static per-provider value
- support 3rd-party-init-SSO with additional authentication request params when a single static provider has been configured
- add support for an empty OIDCClaimPrefix; can be used with OIDCWhiteListedClaims to protect selected headers
- bump to 2.3.0rc0
05/30/2017
- support sending Authorization Request as "request" object in addition to "request_uri"; thanks @suttod
- support nested claim matching in Require directives; thanks @suttod
- support explicitly setting the "kid" of the private key in OIDCPrivateKeyFiles; thanks @suttod
05/25/2017
- fix cache fallback so it happens (when enabled) only after failure
05/19/2017
- make OIDCStripCookies work on AuthType oauth20 paths; closes #273; thanks Michele Danieli
- bump to 2.2.1rc6
05/18/2017
- fix parse function of OIDCRequestObject configuration option; thanks @suttod
05/17/2017
- avoid crash when the X-Forwarded-Proto header is not correctly set by a reverse proxy in front of mod_auth_openidc
05/14/2017
- support JWT verification against multiple keys with no provided kid by looping over the provided keys with cjose 0.5.0
- remove OIDC RP certification files; moved to separate repository
05/04/2017
- improve documentation for OIDCCryptoPassphrase; closes #268
04/30/2017
- fix wrong return value for cache_file_set in the file cache backend (OIDCCacheType file); thanks Ernani Joppert Pontes Martins
- bump to 2.2.1rc5
04/29/2017
- correctly log success/failure in cache_file_set
- avoid decoding a JSON object and logging an error when the input is NULL
e.g. when claims have not been resolved because userinfo endpoint is not set
04/20/2017
- support relative RedirectURIs; closes #200; thanks @moschlar
- don't assume that having OIDCCryptPassphrase set means we should validate the config for
openid-connect since it can now also be used to encrypt (auth20) cache entries
- bump to 2.2.1rc4
04/08/2017
- fix potential crash on prefork process exit when used with Redis cache backend (3x)
- bump to 2.2.1rc3
04/06/2017
- change warn log about missing token binding ID to debug log
04/05/2017
- allow for high session inactivity timeout max value
- improve error message in oidc_util_http_send when ap_pass_brigade fails and mention possible interference with mod_deflate
- bump to 2.2.1rc0
03/30/2017
- merge feature branch back to master:
- better support for Single Page Applications, see:
https://github.com/pingidentity/mod_auth_openidc/wiki/Single-Page-Applications
- add session info hook that is configurable through OIDCInfoHook
- add "AuthType auth-openidc" option that allows both "oauth20" and "openid-connect" on the same path
- add encryption for all cache entries instead of just session data through OIDCCacheEncrypt
- add cookie SameSite flag/policy through OIDCCookieSameSite
- return HTTP 200 on OPTIONS requests to (unauthenticated) "oauth20" paths
- add fallback to a by-value session cookie if the primary session cache fails with OIDCSessionCacheFallbackToCookie
- add support for black- and/or white-listing claims with OIDCBlackListedClaims and OIDCWhiteListedClaims
- add prototype token binding support in conjunction with:
https://github.com/zmartzone/mod_token_binding:
- for state & session cookies, see:
https://github.com/TokenBinding/Internet-Drafts
- for ID tokens with OpenID Connect Token Bound Authentication support, see:
http://openid.net/specs/openid-connect-token-bound-authentication-1_0.html
- for Authorization Codes with OAuth 2.0 Token Binding for Authorization Codes, see:
https://tools.ietf.org/html/draft-ietf-oauth-token-binding
- refactoring:
- refactor session state, proto state and headers into getters/setters functions
- refactor PKCE support
- fix removing session state from cache on logout
- fix clearing chunked session cookies on logout; closes #246; thanks @Jharmuth
- release 2.2.0
02/20/2017
- security fix: scrub headers for "AuthType oauth20"
- release 2.1.6
......
......@@ -3,7 +3,7 @@ SRC=src/mod_auth_openidc.c \
src/cache/file.c \
src/cache/memcache.c \
src/cache/shm.c \
src/cache/lock.c \
src/cache/common.c \
src/oauth.c \
src/proto.c \
src/config.c \
......@@ -21,6 +21,11 @@ REDIS_CFLAGS=-DUSE_LIBHIREDIS @HIREDIS_CFLAGS@
REDIS_LIBS=@HIREDIS_LIBS@
endif
ifeq (@HAVE_LIBJQ@, 1)
JQ_CFLAGS=-DUSE_LIBJQ @JQ_CFLAGS@
JQ_LIBS=@JQ_LIBS@
endif
HDRS = \
$(JWT_HDRS) \
src/mod_auth_openidc.h \
......@@ -48,8 +53,8 @@ DISTFILES=$(SRC) \
all: src/mod_auth_openidc.la
CFLAGS=@OPENSSL_CFLAGS@ @CURL_CFLAGS@ @JANSSON_CFLAGS@ @CJOSE_CFLAGS@ @PCRE_CFLAGS@ $(REDIS_CFLAGS)
LIBS=@OPENSSL_LIBS@ @CURL_LIBS@ @JANSSON_LIBS@ @CJOSE_LIBS@ @PCRE_LIBS@ $(REDIS_LIBS)
CFLAGS=@OPENSSL_CFLAGS@ @CURL_CFLAGS@ @JANSSON_CFLAGS@ @CJOSE_CFLAGS@ @PCRE_CFLAGS@ $(REDIS_CFLAGS) $(JQ_CFLAGS)
LIBS=@OPENSSL_LIBS@ @CURL_LIBS@ @JANSSON_LIBS@ @CJOSE_LIBS@ @PCRE_LIBS@ $(REDIS_LIBS) $(JQ_LIBS)
src/mod_auth_openidc.la: $(SRC) $(HDRS)
@APXS2@ @APXS2_OPTS@ -Wc,"-DNAMEVER=\"@NAMEVER@\" $(CFLAGS)" -Wl,"$(LIBS)" -Wc,-Wall -Wc,-g -c $(SRC)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
AC_INIT([mod_auth_openidc],[2.1.6],[hans.zandbelt@zmartzone.eu])
AC_INIT([mod_auth_openidc],[2.3.1],[hans.zandbelt@zmartzone.eu])
AC_SUBST(NAMEVER, AC_PACKAGE_TARNAME()-AC_PACKAGE_VERSION())
......@@ -86,6 +86,31 @@ AC_SUBST(HAVE_LIBHIREDIS)
AC_SUBST(HIREDIS_CFLAGS)
AC_SUBST(HIREDIS_LIBS)
# JQ
HAVE_LIBJQ=0
AC_ARG_WITH(jq,
[ --with-jq=PATH location of your libjq installation])
if test -n "$with_jq"
then
JQ_CFLAGS="-I$with_jq/include"
JQ_LIBS="-L$with_jq/lib -ljq"
CPPFLAGS="$JQ_CFLAGS $CPPFLAGS"
AC_CHECK_HEADERS([jq.h], , [HAVE_LIBJQ=0])
LDFLAGS="$JQ_LIBS $LDFLAGS"
AC_CHECK_LIB([jq], [jq_init], [HAVE_LIBJQ=1], [HAVE_LIBJQ=0])
if test "x$have_jq" = "x0" ; then
AC_MSG_WARN("cannot find library for -ljq.")
fi
fi
AC_SUBST(HAVE_LIBJQ)
AC_SUBST(JQ_CFLAGS)
AC_SUBST(JQ_LIBS)
# Create Makefile from Makefile.in
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
......@@ -58,6 +58,10 @@
#include <pcre.h>
#ifdef USE_LIBJQ
#include "jq.h"
#endif
static apr_byte_t oidc_authz_match_value(request_rec *r, const char *spec_c,
json_t *val, const char *key) {
......@@ -101,7 +105,7 @@ static apr_byte_t oidc_authz_match_value(request_rec *r, const char *spec_c,
} else if (json_is_boolean(elem)) {
if (apr_strnatcmp(
json_is_true(elem) ? "true" : "false", spec_c) == 0)
json_is_true(elem) ? "true" : "false", spec_c) == 0)
return TRUE;
} else if (json_is_integer(elem)) {
......@@ -180,7 +184,7 @@ static apr_byte_t oidc_authz_match_expression(request_rec *r,
/*
* see if a the Require value matches with a set of provided claims
*/
static apr_byte_t oidc_authz_match_claim(request_rec *r,
apr_byte_t oidc_authz_match_claim(request_rec *r,
const char * const attr_spec, const json_t * const claims) {
const char *key;
......@@ -209,7 +213,7 @@ static apr_byte_t oidc_authz_match_claim(request_rec *r,
}
/* The match is a success if we walked the whole claim name and the attr_spec is at a colon. */
if (!(*attr_c) && (*spec_c) == ':') {
if (!(*attr_c) && (*spec_c) == OIDC_CHAR_COLON) {
/* skip the colon */
spec_c++;
......@@ -218,13 +222,28 @@ static apr_byte_t oidc_authz_match_claim(request_rec *r,
return TRUE;
/* a tilde denotes a string PCRE match */
} else if (!(*attr_c) && (*spec_c) == '~') {
} else if (!(*attr_c) && (*spec_c) == OIDC_CHAR_TILDE) {
/* skip the tilde */
spec_c++;
if (oidc_authz_match_expression(r, spec_c, val) == TRUE)
return TRUE;
/* dot means child nodes must be evaluated */
} else if (!(*attr_c) && (*spec_c) == OIDC_CHAR_DOT) {
/* skip the dot */
spec_c++;
if (!json_is_object(val)) {
oidc_warn(r, "\"%s\" matched, and child nodes should be evaluated, but value is not an object.", key);
return FALSE;
}
oidc_debug(r, "Attribute chunk matched. Evaluating children of key: \"%s\".", key);
return oidc_authz_match_claim(r, spec_c, json_object_get(claims, key));
}
iter = json_object_iter_next((json_t *) claims, iter);
......@@ -233,10 +252,73 @@ static apr_byte_t oidc_authz_match_claim(request_rec *r,
return FALSE;
}
#ifdef USE_LIBJQ
static apr_byte_t jq_parse(request_rec *r, jq_state *jq, struct jv_parser *parser) {
apr_byte_t rv = FALSE;
jv value;
while (jv_is_valid((value = jv_parser_next(parser)))) {
jq_start(jq, value, 0);
jv result;
while (jv_is_valid(result = jq_next(jq))) {
jv dumped = jv_dump_string(result, 0);
const char *str = jv_string_value(dumped);
oidc_debug(r, "dumped: %s", str);
rv = (apr_strnatcmp(str, "true") == 0);
}
jv_free(result);
}
if (jv_invalid_has_msg(jv_copy(value))) {
jv msg = jv_invalid_get_msg(value);
oidc_error(r, "invalid: %s", jv_string_value(msg));
jv_free(msg);
rv = FALSE;
} else {
jv_free(value);
}
return rv;
}
/*
* see if a the Require value matches a configured expression
*/
apr_byte_t oidc_authz_match_claims_expr(request_rec *r,
const char * const attr_spec, const json_t * const claims) {
apr_byte_t rv = FALSE;
oidc_debug(r, "enter: '%s'", attr_spec);
jq_state *jq = jq_init();
if (jq_compile(jq, attr_spec) == 0) {
jq_teardown(&jq);
return FALSE;
}
struct jv_parser *parser = jv_parser_new(0);
char *buf = oidc_util_encode_json_object(r, (json_t *)claims, 0);
jv_parser_set_buf(parser, buf, strlen(buf), 0);
rv = jq_parse(r, jq, parser);
jv_parser_free(parser);
jq_teardown(&jq);
return rv;
}
#endif
#if MODULE_MAGIC_NUMBER_MAJOR < 20100714
/*
* Apache <2.4 authorization routine: match the claims from the authenticated user against the Require primitive
*/
int oidc_authz_worker(request_rec *r, const json_t * const claims,
int oidc_authz_worker22(request_rec *r, const json_t * const claims,
const require_line * const reqs, int nelts) {
const int m = r->method_number;
const char *token;
......@@ -244,6 +326,7 @@ int oidc_authz_worker(request_rec *r, const json_t * const claims,
int i;
int have_oauthattr = 0;
int count_oauth_claims = 0;
oidc_authz_match_claim_fn_type match_claim_fn = NULL;
/* go through applicable Require directives */
for (i = 0; i < nelts; ++i) {
......@@ -258,11 +341,18 @@ int oidc_authz_worker(request_rec *r, const json_t * const claims,
token = ap_getword_white(r->pool, &requirement);
if (apr_strnatcasecmp(token, OIDC_REQUIRE_NAME) != 0) {
/* see if we've got anything meant for us */
if (apr_strnatcasecmp(token, OIDC_REQUIRE_CLAIM_NAME) == 0) {
match_claim_fn = oidc_authz_match_claim;
#ifdef USE_LIBJQ
} else if (apr_strnatcasecmp(token, OIDC_REQUIRE_CLAIMS_EXPR_NAME) == 0) {
match_claim_fn = oidc_authz_match_claims_expr;
#endif
} else {
continue;
}
/* ok, we have a "Require claim" to satisfy */
/* ok, we have a "Require claim/claims_expr" to satisfy */
have_oauthattr = 1;
/*
......@@ -276,18 +366,18 @@ int oidc_authz_worker(request_rec *r, const json_t * const claims,
/*
* iterate over the claim specification strings in this require directive searching
* for a specification that matches one of the claims.
* for a specification that matches one of the claims/expressions.
*/
while (*requirement) {
token = ap_getword_conf(r->pool, &requirement);
count_oauth_claims++;
oidc_debug(r, "evaluating claim specification: %s", token);
oidc_debug(r, "evaluating claim/expr specification: %s", token);
if (oidc_authz_match_claim(r, token, claims) == TRUE) {
if (match_claim_fn(r, token, claims) == TRUE) {
/* if *any* claim matches, then authorization has succeeded and all of the others are ignored */
oidc_debug(r, "require claim '%s' matched", token);
oidc_debug(r, "require claim/expr '%s' matched", token);
return OK;
}
}
......@@ -295,13 +385,13 @@ int oidc_authz_worker(request_rec *r, const json_t * const claims,
/* if there weren't any "Require claim" directives, we're irrelevant */
if (!have_oauthattr) {
oidc_debug(r, "no claim statements found, not performing authz");
oidc_debug(r, "no claim/expr statements found, not performing authz");
return DECLINED;
}
/* if there was a "Require claim", but no actual claims, that's cause to warn the admin of an iffy configuration */
if (count_oauth_claims == 0) {
oidc_warn(r,
"'require claim' missing specification(s) in configuration, declining");
"'require claim/expr' missing specification(s) in configuration, declining");
return DECLINED;
}
......@@ -312,20 +402,24 @@ int oidc_authz_worker(request_rec *r, const json_t * const claims,
return HTTP_UNAUTHORIZED;
}
#if MODULE_MAGIC_NUMBER_MAJOR >= 20100714
#else
/*
* Apache >=2.4 authorization routine: match the claims from the authenticated user against the Require primitive
*/
authz_status oidc_authz_worker24(request_rec *r, const json_t * const claims, const char *require_args) {
authz_status oidc_authz_worker24(request_rec *r, const json_t * const claims,
const char *require_args, oidc_authz_match_claim_fn_type match_claim_fn) {
int count_oauth_claims = 0;
const char *t, *w;
/* needed for anonymous authentication */
if (r->user == NULL) return AUTHZ_DENIED_NO_USER;
if (r->user == NULL)
return AUTHZ_DENIED_NO_USER;
/* if no claims, impossible to satisfy */
if (!claims) return AUTHZ_DENIED;
if (!claims)
return AUTHZ_DENIED;
/* loop over the Required specifications */
t = require_args;
......@@ -333,12 +427,12 @@ authz_status oidc_authz_worker24(request_rec *r, const json_t * const claims, co
count_oauth_claims++;
oidc_debug(r, "evaluating claim specification: %s", w);
oidc_debug(r, "evaluating claim/expr specification: %s", w);
/* see if we can match any of out input claims against this Require'd value */
if (oidc_authz_match_claim(r, w, claims) == TRUE) {
if (match_claim_fn(r, w, claims) == TRUE) {
oidc_debug(r, "require claim '%s' matched", w);
oidc_debug(r, "require claim/expr '%s' matched", w);
return AUTHZ_GRANTED;
}
}
......@@ -346,9 +440,10 @@ authz_status oidc_authz_worker24(request_rec *r, const json_t * const claims, co
/* if there wasn't anything after the Require claims directive... */
if (count_oauth_claims == 0) {
oidc_warn(r,
"'require claim' missing specification(s) in configuration, denying");
"'require claim/expr' missing specification(s) in configuration, denying");
}
return AUTHZ_DENIED;
}
#endif
......@@ -66,8 +66,8 @@ typedef apr_byte_t (*oidc_cache_set_function)(request_rec *r,
typedef int (*oidc_cache_destroy_function)(server_rec *s);
typedef struct oidc_cache_t {
apr_byte_t secure;
oidc_cache_cfg_create create_config;
const char *name;
int encrypt_by_default;
oidc_cache_post_config_function post_config;
oidc_cache_child_init_function child_init;
oidc_cache_get_function get;
......@@ -89,6 +89,35 @@ apr_byte_t oidc_cache_mutex_lock(request_rec *r, oidc_cache_mutex_t *m);
apr_byte_t oidc_cache_mutex_unlock(request_rec *r, oidc_cache_mutex_t *m);
apr_byte_t oidc_cache_mutex_destroy(server_rec *s, oidc_cache_mutex_t *m);
apr_byte_t oidc_cache_get(request_rec *r, const char *section, const char *key,
char **value);
apr_byte_t oidc_cache_set(request_rec *r, const char *section, const char *key,
const char *value, apr_time_t expiry);
#define OIDC_CACHE_SECTION_SESSION "s"
#define OIDC_CACHE_SECTION_NONCE "n"
#define OIDC_CACHE_SECTION_JWKS "j"
#define OIDC_CACHE_SECTION_ACCESS_TOKEN "a"
#define OIDC_CACHE_SECTION_PROVIDER "p"
#define OIDC_CACHE_SECTION_JTI "t"
#define OIDC_CACHE_SECTION_REQUEST_URI "r"
#define oidc_cache_get_session(r, key, value) oidc_cache_get(r, OIDC_CACHE_SECTION_SESSION, key, value)
#define oidc_cache_get_nonce(r, key, value) oidc_cache_get(r, OIDC_CACHE_SECTION_NONCE, key, value)
#define oidc_cache_get_jwks(r, key, value) oidc_cache_get(r, OIDC_CACHE_SECTION_JWKS, key, value)
#define oidc_cache_get_access_token(r, key, value) oidc_cache_get(r, OIDC_CACHE_SECTION_ACCESS_TOKEN, key, value)
#define oidc_cache_get_provider(r, key, value) oidc_cache_get(r, OIDC_CACHE_SECTION_PROVIDER, key, value)
#define oidc_cache_get_jti(r, key, value) oidc_cache_get(r, OIDC_CACHE_SECTION_JTI, key, value)
#define oidc_cache_get_request_uri(r, key, value) oidc_cache_get(r, OIDC_CACHE_SECTION_REQUEST_URI, key, value)
#define oidc_cache_set_session(r, key, value, expiry) oidc_cache_set(r, OIDC_CACHE_SECTION_SESSION, key, value, expiry)
#define oidc_cache_set_nonce(r, key, value, expiry) oidc_cache_set(r, OIDC_CACHE_SECTION_NONCE, key, value, expiry)
#define oidc_cache_set_jwks(r, key, value, expiry) oidc_cache_set(r, OIDC_CACHE_SECTION_JWKS, key, value, expiry)
#define oidc_cache_set_access_token(r, key, value, expiry) oidc_cache_set(r, OIDC_CACHE_SECTION_ACCESS_TOKEN, key, value, expiry)
#define oidc_cache_set_provider(r, key, value, expiry) oidc_cache_set(r, OIDC_CACHE_SECTION_PROVIDER, key, value, expiry)
#define oidc_cache_set_jti(r, key, value, expiry) oidc_cache_set(r, OIDC_CACHE_SECTION_JTI, key, value, expiry)
#define oidc_cache_set_request_uri(r, key, value, expiry) oidc_cache_set(r, OIDC_CACHE_SECTION_REQUEST_URI, key, value, expiry)
extern oidc_cache_t oidc_cache_file;
extern oidc_cache_t oidc_cache_memcache;
extern oidc_cache_t oidc_cache_shm;
......
This diff is collapsed.
......@@ -75,7 +75,7 @@ typedef struct {
/*
* prefix that distinguishes mod_auth_openidc cache files from other files in the same directory (/tmp)
*/
#define OIDC_CACHE_FILE_PREFIX "mod-auth-connect-"
#define OIDC_CACHE_FILE_PREFIX "mod-auth-openidc-"
/* post config routine */
int oidc_cache_file_post_config(server_rec *s) {
......@@ -95,7 +95,7 @@ int oidc_cache_file_post_config(server_rec *s) {
static const char *oidc_cache_file_name(request_rec *r, const char *section,
const char *key) {
return apr_psprintf(r->pool, "%s%s-%s", OIDC_CACHE_FILE_PREFIX, section,
key);
oidc_util_escape_string(r, key));
}
/*
......@@ -184,7 +184,7 @@ static apr_byte_t oidc_cache_file_get(request_rec *r, const char *section,
/* open the cache file if it exists, otherwise we just have a "regular" cache miss */
if (apr_file_open(&fd, path, APR_FOPEN_READ | APR_FOPEN_BUFFERED,
APR_OS_DEFAULT, r->pool) != APR_SUCCESS) {
APR_OS_DEFAULT, r->pool) != APR_SUCCESS) {
oidc_debug(r, "cache miss for key \"%s\"", key);
return TRUE;
}
......@@ -239,11 +239,6 @@ static apr_byte_t oidc_cache_file_get(request_rec *r, const char *section,
apr_file_unlock(fd);
apr_file_close(fd);
/* log a successful cache hit */
oidc_debug(r,
"cache hit for key \"%s\" (%" APR_SIZE_T_FMT " bytes, expiring in: %" APR_TIME_T_FMT ")",
key, info.len, apr_time_sec(info.expire - apr_time_now()));
return TRUE;
error_close:
......@@ -295,6 +290,8 @@ static apr_status_t oidc_cache_file_clean(request_rec *r) {
/* time to clean, reset the modification time of the metadata file to reflect the timestamp of this cleaning cycle */
apr_file_mtime_set(metadata_path, apr_time_now(), r->pool);
oidc_debug(r, "start cleaning cycle");
} else {
/* no metadata file exists yet, create one (and open it) */
......@@ -329,7 +326,7 @@ static apr_status_t oidc_cache_file_clean(request_rec *r) {
if (i == APR_SUCCESS) {
/* skip non-cache entries, cq. the ".", ".." and the metadata file */
if ((fi.name[0] == '.')
if ((fi.name[0] == OIDC_CHAR_DOT)
|| (strstr(fi.name, OIDC_CACHE_FILE_PREFIX) != fi.name)
|| ((apr_strnatcmp(fi.name,
oidc_cache_file_name(r, "cache-file",
......@@ -412,7 +409,8 @@ static apr_byte_t oidc_cache_file_set(request_rec *r, const char *section,
}
/* try to open the cache file for writing, creating it if it does not exist */
if ((rc = apr_file_open(&fd, path, (APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE),
if ((rc = apr_file_open(&fd, path,
(APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE),
APR_OS_DEFAULT, r->pool)) != APR_SUCCESS) {
oidc_error(r, "cache file \"%s\" could not be opened (%s)", path,
apr_strerror(rc, s_err, sizeof(s_err)));
......@@ -435,25 +433,24 @@ static apr_byte_t oidc_cache_file_set(request_rec *r, const char *section,
return FALSE;
/* next write the value */
if ((rc = oidc_cache_file_write(r, path, fd, (void *) value, info.len))
!= APR_SUCCESS)
return FALSE;
rc = oidc_cache_file_write(r, path, fd, (void *) value, info.len);
/* unlock and close the written file */
apr_file_unlock(fd);
apr_file_close(fd);
/* log our success */
/* log our success/failure */
oidc_debug(r,
"set entry for key \"%s\" (%" APR_SIZE_T_FMT " bytes, expires in: %" APR_TIME_T_FMT ")",
key, info.len, apr_time_sec(expiry - apr_time_now()));
"%s entry for key \"%s\" in file of %" APR_SIZE_T_FMT " bytes",
(rc == APR_SUCCESS) ? "successfully stored" : "could not store",
key, info.len);
return TRUE;
return (rc == APR_SUCCESS);
}
oidc_cache_t oidc_cache_file = {
"file",
1,
NULL,
oidc_cache_file_post_config,
NULL,
oidc_cache_file_get,
......
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/***************************************************************************
* Copyright (C) 2013-2017 Ping Identity Corporation
* All rights reserved.
*
* For further information please contact:
*
* Ping Identity Corporation
* 1099 18th St Suite 2950
* Denver, CO 80202
* 303.468.2900
* http://www.pingidentity.com
*
* DISCLAIMER OF WARRANTIES:
*
* THE SOFTWARE PROVIDED HEREUNDER IS PROVIDED ON AN "AS IS" BASIS, WITHOUT
* ANY WARRANTIES OR REPRESENTATIONS EXPRESS, IMPLIED OR STATUTORY; INCLUDING,
* WITHOUT LIMITATION, WARRANTIES OF QUALITY, PERFORMANCE, NONINFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. NOR ARE THERE ANY
* WARRANTIES CREATED BY A COURSE OR DEALING, COURSE OF PERFORMANCE OR TRADE
* USAGE. FURTHERMORE, THERE ARE NO WARRANTIES THAT THE SOFTWARE WILL MEET
* YOUR NEEDS OR BE FREE FROM ERRORS, OR THAT THE OPERATION OF THE SOFTWARE
* WILL BE UNINTERRUPTED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* global lock implementation
*
* @Author: Hans Zandbelt - hans.zandbelt@zmartzone.eu
*/
#ifndef WIN32
#include <unistd.h>
#endif
#include "apr_general.h"
#include <httpd.h>
#include <http_config.h>
#include <http_log.h>
#ifdef AP_NEED_SET_MUTEX_PERMS
#include "unixd.h"
#endif
#include "../mod_auth_openidc.h"
/* create the cache lock context */
oidc_cache_mutex_t *oidc_cache_mutex_create(apr_pool_t *pool) {
oidc_cache_mutex_t *ctx = apr_pcalloc(pool, sizeof(oidc_cache_mutex_t));
ctx->mutex = NULL;
ctx->mutex_filename = NULL;
return ctx;
}
apr_byte_t oidc_cache_mutex_post_config(server_rec *s, oidc_cache_mutex_t *m,
const char *type) {
apr_status_t rv = APR_SUCCESS;
const char *dir;
/* construct the mutex filename */
apr_temp_dir_get(&dir, s->process->pool);
m->mutex_filename = apr_psprintf(s->process->pool,
"%s/mod_auth_openidc_%s_mutex.%ld.%pp", dir, type,
(long int) getpid(), s);
/* create the mutex lock */
rv = apr_global_mutex_create(&m->mutex, (const char *) m->mutex_filename,
APR_LOCK_DEFAULT, s->process->pool);
if (rv != APR_SUCCESS) {
oidc_serror(s,
"apr_global_mutex_create failed to create mutex on file %s",
m->mutex_filename);
return FALSE;
}
/* need this on Linux */
#ifdef AP_NEED_SET_MUTEX_PERMS
#if MODULE_MAGIC_NUMBER_MAJOR >= 20081201
rv = ap_unixd_set_global_mutex_perms(m->mutex);
#else
rv = unixd_set_global_mutex_perms(m->mutex);
#endif
if (rv != APR_SUCCESS) {
oidc_serror(s,
"unixd_set_global_mutex_perms failed; could not set permissions ");
return FALSE;
}
#endif
return TRUE;
}
/*
* initialize the cache lock in a child process
*/
apr_status_t oidc_cache_mutex_child_init(apr_pool_t *p, server_rec *s,
oidc_cache_mutex_t *m) {
/* initialize the lock for the child process */
apr_status_t rv = apr_global_mutex_child_init(&m->mutex,