Commit 6a5c35b8 authored by Moritz Schlarb's avatar Moritz Schlarb

New upstream version 2.3.7

parent 99f94b06
......@@ -40,3 +40,9 @@ reporting bugs, providing fixes, suggesting useful features or other:
hihellobolke <https://github.com/hihellobolke>
Horatiu Eugen Vlad <https://github.com/iconoeugen>
cristichiru <https://github.com/cristichiru>
Bono de Visser <https://github.com/kerrermanisNL>
Patrick Uiterwijk <https://github.com/puiterwijk>
Marcel Kottmann <https://github.com/pepe79>
timpuri <https://github.com/timpuri>
Eldar Zaitov <https://github.com/kyprizel>
Gergan Penkov <https://github.com/gergan>
07/06/2018
- abort when string length for remote user name substitution is larger than 255 characters
- release 2.3.7
07/04/2018
- fix Redis concurrency issue when used with multiple vhosts
- bump to 2.3.7rc4 and 2.3.7rc5
06/29/2018
- add support for authorization server metadata with OIDCOAuthServerMetadataURL as in RFC 8414
- bump to 2.3.7rc3
06/23/2018
- refactor session object creation
- bump to 2.3.7rc2
06/22/2018
- clear session cookie and contents if cache corruption is detected
- bump to 2.3.7rc0
- use apr_pstrdup when setting r->user
- reserve 255 characters in remote username substition instead of 50
- bump to 2.3.7rc1
06/15/2018
- add check to detect session cache corruption for server-based caches and cached static metadata
- release 2.3.6
05/29/2018
- avoid using pipelining for Redis
- bump to 2.3.6rc4
05/28/2018
- send Basic header in OAuth www-authenticate response if that's the only accepted method; thanks @puiterwijk
05/28/2018
- refactor Redis cache backend to solve issues on AUTH errors: a) memory leak and b) redisGetReply lagging behind
- adjust copyright year/org
- bump to 2.3.6rc3
05/23/2018
- fix buffer overflow in shm cache key set strcpy; thanks @kyprizel
- bump to 2.3.6rc2
05/22/2018
- turn missing session_state from warning into a debug statement
- fix missing "return" on error return from the OP; see #345; thanks @gergan
- bump to 2.3.6rc1
05/19/2018
- explicitly set encryption kid so we're compatible with cjose >= 0.6.0
- bump to 2.3.6rc0
05/18/2018
- fix encoding of preserved POST data; see #338; thanks @timpuri
- avoid buffer overflow in shm cache key construction; thanks @kyprizel
- release 2.3.5
05/08/2018
- compile with with Libressl; closes #358; thanks @hihellobolke
- bump to 2.3.5rc0
04/27/2018
- avoid crash when a relative logout URL parameter is passed in; thanks Vivien Delenne
- release 2.3.4
03/22/2018
- interpret X-Forwarded-Host when doing XSRF protection on the after-logout URL; see #341; thanks @pepe79
- bump to 2.3.4rc4
02/06/2018
- add support for passing an access token in a HTTP Basic authentication password; thanks @puiterwijk
- bump to 2.3.4rc3
01/26/2018
- send session management Javascript logging to debug; thanks @kerrermanisNL
01/25/2018
- add Cache-Control no-cache header to authorization requests to avoid replays of state/nonce; see #321
- bump to 2.3.4rc2
01/23/2018
- add explicit endpoint authentication method "bearer_access_token"
12/29/2017
- correct documentation on kid usage for OIDCOAuthVerifyCertFiles; closes #318
12/21/2017
- fix compiler warnings for OpenSSL 1.1.x
- bump to 2.3.4rc1
11/21/2017
- fix bug where endpoint authentication method "private_key_jwt" would not co-exist with "none"
- bump to 2.3.4rc0
11/16/2017
- add support for passing userinfo as a JSON object or JWT; see #311
- release 2.3.3
......
/***************************************************************************
* Copyright (C) 2014-2017 Ping Identity Corporation
* All rights reserved.
*
* 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.
*/
......@@ -48,7 +48,6 @@ DISTFILES=$(SRC) \
INSTALL \
README.md \
AUTHORS \
DISCLAIMER \
auth_openidc.conf \
LICENSE.txt \
ChangeLog
......@@ -67,7 +66,7 @@ configure: configure.ac
@NAMEVER@.tar.gz: $(DISTFILES)
tar -c --transform="s#^#@NAMEVER@/#" -vzf $@ $(DISTFILES)
test/test test/test-cmd: test/test.c test/stub.c src/mod_auth_openidc.la
test/test test/test-cmd: test/test.c test/test-cmd.c test/stub.c src/mod_auth_openidc.la
@APXS2@ @APXS2_OPTS@ $(CFLAGS) -Wl,"$(LIBS)" -Isrc -Wc,-Wall -Wc,-g -c -o $@ $@.c test/stub.c $(SRC:.c=.lo) @APR_LIBS@
test-compile: test/test test/test-cmd
......
[![Build Status](https://travis-ci.org/zmartzone/mod_auth_openidc.svg?branch=master)](https://travis-ci.org/zmartzone/mod_auth_openidc)
[<img width="184" height="96" align="right" src="http://openid.net/wordpress-content/uploads/2016/04/oid-l-certification-mark-l-rgb-150dpi-90mm@2x.png" alt="OpenID Certification">](https://openid.net/certification)
mod_auth_openidc
================
......@@ -6,18 +7,18 @@ mod_auth_openidc
*mod_auth_openidc* is an authentication/authorization module for the Apache 2.x
HTTP server that functions as an **OpenID Connect Relying Party**, authenticating users against an
OpenID Connect Provider. It can also function as an **OAuth 2.0 Resource Server**, validating
OAuth 2.0 access tokens presented by OAuth 2.0 Clients.
OAuth 2.0 bearer access tokens presented by OAuth 2.0 Clients.
Overview
--------
This module enables an Apache 2.x web server to operate as an [OpenID Connect](http://openid.net/specs/openid-connect-core-1_0.html)
*Relying Party* (RP) to an OpenID Connect *Provider* (OP). It authenticates users against an OpenID Connect Provider,
receives user identity information from the OP in a so called ID Token and passes the identity information
receives user identity information from the OP in a so called ID Token and passes on the identity information
(a.k.a. claims) in the ID Token to applications hosted and protected by the Apache web server.
It can also be configured as an OAuth 2.0 *Resource Server* (RS), consuming bearer access tokens and validating
them against an OAuth 2.0 Authorization Server, authorizing the Clients based on the validation results.
them against an OAuth 2.0 Authorization Server, authorizing Clients based on the validation results.
The protected content and/or applications can be served by the Apache server itself or it can be served from elsewhere
when Apache is configured as a Reverse Proxy in front of the origin server(s).
......@@ -30,20 +31,26 @@ It allows for authorization rules (based on standard Apache `Require` primitives
of claims provided in the `id_token`/ `userinfo` claims.
*mod_auth_openidc* supports the following specifications:
- [OpenID Connect](http://openid.net/specs/openid-connect-core-1_0.html) Basic, Implicit, Hybrid and Refresh flows.
- [OpenID Connect Dynamic Client Registration](http://openid.net/specs/openid-connect-registration-1_0.html)
- [OpenID Provider Discovery](http://openid.net/specs/openid-connect-discovery-1_0.html)
- [OAuth 2.0 Form Post Response Mode](http://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html)
- [Proof Key for Code Exchange by OAuth Public Clients](https://tools.ietf.org/html/rfc7636)
- [OpenID Connect Session Management](http://openid.net/specs/openid-connect-session-1_0.html). See the [Wiki](https://github.com/zmartzone/mod_auth_openidc/wiki/Session-Management) for information
on how to configure it.
- [OpenID Connect Core 1.0](http://openid.net/specs/openid-connect-core-1_0.html) *(Basic, Implicit, Hybrid and Refresh flows)*
- [OpenID Connect Discovery 1.0](http://openid.net/specs/openid-connect-discovery-1_0.html)
- [OpenID Connect Dynamic Client Registration 1.0](http://openid.net/specs/openid-connect-registration-1_0.html)
- [OAuth 2.0 Multiple Response Type Encoding Practices 1.0](http://openid.net/specs/oauth-v2-multiple-response-types-1_0.html)
- [OAuth 2.0 Form Post Response Mode 1.0](http://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html)
- [RFC7 7636 - Proof Key for Code Exchange by OAuth Public Clients](https://tools.ietf.org/html/rfc7636)
- [OpenID Connect Session Management 1.0](http://openid.net/specs/openid-connect-session-1_0.html) *(implementers draft; see the [Wiki](https://github.com/zmartzone/mod_auth_openidc/wiki/Session-Management) for information on how to configure it)*
- [OpenID Connect Front-Channel Logout 1.0](http://openid.net/specs/openid-connect-frontchannel-1_0.html) *(implementers draft)*
- [Encoding claims in the OAuth 2 state parameter using a JWT](https://tools.ietf.org/html/draft-bradley-oauth-jwt-encoded-state-08) *(draft spec)*
- [OpenID Connect Token Bound Authentication](https://openid.net/specs/openid-connect-token-bound-authentication-1_0.html) *(draft spec; when combined with [mod_token_binding](https://github.com/zmartzone/mod_token_binding))*
Alternatively the module can operate as an OAuth 2.0 Resource Server to an OAuth 2.0 Authorization Server,
introspecting/validating bearer Access Tokens conforming to [OAuth 2.0 Token Introspection](https://tools.ietf.org/html/rfc7662) (or similar),
or verifiying them locally if they are JWTs.
validating bearer Access Tokens by introspecting them or verifying them locally if they are JWTs.
In the OAuth 2.0 Resource Server mode *mod_auth_openidc* supports the following specifications:
- [RFC 6750 - The OAuth 2.0 Authorization Framework: Bearer Token Usage](https://tools.ietf.org/html/rfc6750)
- [RFC 7662 - OAuth 2.0 Token Introspection](https://tools.ietf.org/html/rfc7662) (or similar)
- [RFC 8414 - OAuth 2.0 Authorization Server Metadata](https://tools.ietf.org/html/rfc8414)
The `REMOTE_USER` variable setting, passing claims in HTTP headers and authorization based on `Require` primitives
works in the same way as described for OpenID Connect above. See the [Wiki](https://github.com/zmartzone/mod_auth_openidc/wiki/OAuth-2.0-Resource-Server) for information
on how to configure it.
works in the same way as described for OpenID Connect above. See the [Wiki](https://github.com/zmartzone/mod_auth_openidc/wiki/OAuth-2.0-Resource-Server) for information on how to configure it.
For an exhaustive description of all configuration options, see the file `auth_openidc.conf`
in this directory. This file can also serve as an include file for `httpd.conf`.
......@@ -85,6 +92,25 @@ Require claim hd:<your-domain>
The above is an authorization example of an exact match of a provided claim against a string value.
For more authorization options see the [Wiki page on Authorization](https://github.com/zmartzone/mod_auth_openidc/wiki/Authorization).
### OpenID Connect SSO with Keycloak
See also the [Wiki page on Keycloak](https://github.com/zmartzone/mod_auth_openidc/wiki/Keycloak)
```apache
OIDCProviderMetadataURL https://keycloak.example.net/auth/realms/master/.well-known/openid-configuration
OIDCRedirectURI https://www.example.net/oauth2callback
OIDCCryptoPassphrase random1234
OIDCClientID <your-client-id-registered-in-keycloak>
OIDCClientSecret <your-client-secret-registered-in-keycloak>
OIDCRemoteUserClaim email
OIDCScope "openid email"
<Location /example/>
AuthType openid-connect
Require valid-user
</Location>
```
### Quickstart with a generic OpenID Connect Provider
1. install and load `mod_auth_openidc.so` in your Apache server
......@@ -112,30 +138,6 @@ OIDCCryptoPassphrase <password>
```
For details on configuring multiple providers see the [Wiki](https://github.com/zmartzone/mod_auth_openidc/wiki/Multiple-Providers).
### PingFederate OAuth 2.0 Resource Server
Example config for using PingFederate as your OAuth 2.0 Authorization server,
based on the OAuth 2.0 PlayGround configuration and doing claims-based authorization, using
RFC 7662 compliant Token Introspection.
```apache
# remote validation
OIDCOAuthIntrospectionEndpoint https://localhost:9031/as/introspect.oauth2
OIDCOAuthIntrospectionEndpointAuth client_secret_basic
OIDCOAuthRemoteUserClaim Username
OIDCOAuthSSLValidateServer Off
OIDCOAuthClientID rs_client
OIDCOAuthClientSecret 2Federate
<Location /api>
AuthType oauth20
Require claim client_id:ro_client
#Require claim scope~\bprofile\b
</Location>
```
For details and additional options on the OAuth 2.0 Resource Server setup see the [Wiki](https://github.com/zmartzone/mod_auth_openidc/wiki/OAuth-2.0-Resource-Server).
### Quickstart with a generic OAuth 2.0 Resource Server
Using "local" validation of JWT bearer tokens:
......@@ -166,9 +168,7 @@ The corresponding forum/archive is at:
For commercial support and consultancy you can contact:
[info@zmartzone.eu](mailto:info@zmartzone.eu)
Any questions/issues should go to the mailing list or the
primary author [hans.zandbelt@zmartzone.eu](mailto:hans.zandbelt@zmartzone.eu).
The Github issues tracker should be used only for bugs reports and feature requests.
Any questions/issues should go to the mailing list. The Github issues tracker should be used only for bugs reports and feature requests.
Disclaimer
----------
......
......@@ -65,12 +65,11 @@
#OIDCProviderTokenEndpoint <token_endpoint>
# Authentication method for the OpenID Connect Provider Token Endpoint.
# One of "client_secret_basic", "client_secret_post", "client_secret_jwt" or "private_key_jwt".
# When "private_key_jwt" is used, OIDCPrivateKeyFiles and OIDCPublicKeyFiles must have been set.
# When not defined the default method from the specification is used, i.e. "client_secret_basic".
# Used when OIDCProviderMetadataURL is not defined or the metadata obtained from that URL does not set it.
# NB: this can be overridden for dynamic client registration on a per-OP basis in the .conf file using the key: token_endpoint_auth
#OIDCProviderTokenEndpointAuth [ client_secret_basic | client_secret_post | client_secret_jwt | private_key_jwt]
#OIDCProviderTokenEndpointAuth [ client_secret_basic | client_secret_post | client_secret_jwt | private_key_jwt | none ]
# Extra parameters that need to be passed in the POST request to the Token Endpoint.
# Parameter names and values need to be provided in URL-encoded form.
......@@ -271,6 +270,13 @@
#
########################################################################################
# URL where Authorization Provider Provider metadata can be found (e.g. https://example.com/.well-known/oauth-authorization-server)
# as defined in RFC 8414. The obtained metadata will be cached and refreshed every 24 hours.
# If set, individual entries below will not have to be configured but can be used to add
# extra entries/endpoints to settings obtained from the metadata.
# If OIDCOAuthServerMetadataURL is not set, the endpoint entries below it will have to be configured.
#OIDCOAuthServerMetadataURL <url>
# (Mandatory when introspecting opaque access tokens, Optional when performing local JWT access token validation)
# OAuth 2.0 Authorization Server token introspection endpoint (e.g. https://localhost:9031/as/token.oauth2)
#OIDCOAuthIntrospectionEndpoint <token-introspection-endpoint>
......@@ -287,12 +293,11 @@
# has been configured.
# When "private_key_jwt" is used, OIDCPrivateKeyFiles and OIDCPublicKeyFiles must have been set.
# When not defined "client_secret_basic" is used.
#OIDCOAuthIntrospectionEndpointAuth [ client_secret_basic | client_secret_post | client_secret_jwt | private_key_jwt]
#OIDCOAuthIntrospectionEndpointAuth [ client_secret_basic | client_secret_post | client_secret_jwt | private_key_jwt | bearer_access_token | none ]
# Some OP do not accept basic or post, only bearer tokens in the Authorization header.
# Specify here a static token to be used for authorizing the call to the introspection endpoint.
# Used when "OIDCOAuthIntrospectionEndpointAuth bearer_access_token" is configured.
# Specifies a static token to be used for authorizing the call to the introspection endpoint.
# If empty, the introspected token will be used for authorization as well.
# If unset, one of the methods specified by OIDCOAuthIntrospectionEndpointAuth will be used.
#OIDCOAuthIntrospectionClientAuthBearerToken [ a-static-bearer-token | ]
# Filename that contains the PEM-formatted client certificate used to authenticate the
......@@ -356,7 +361,7 @@
# keys that can be used for local JWT access token verification.
# NB: this is one or more key tuples where a key tuple consists of:
# [<key-identifier>#]<path-to-cert>
# and the key identifier part is optional.
# and the key identifier part is required when the JWT access token contains a "kid" in its header.
# When not defined, no access token validation with statically configured certificates will be performed.
#OIDCOAuthVerifyCertFiles ([<kid>#]<filename>)+
......@@ -384,8 +389,9 @@
# "post" : an HTTP Post parameter called "access_token"
# "query" : as an HTTP query parameter called "access_token"
# "cookie" : as a cookie header called "PA.global" or using the name specified after ":"
# "basic": as a HTTP Basic Auth (RFC2617, section 2) password, with any username
# When not defined the default "header" is used.
#OIDCOAuthAcceptTokenAs [header|post|query|cookie[:<cookie-name>]+
#OIDCOAuthAcceptTokenAs [header|post|query|cookie[:<cookie-name>|basic]+
########################################################################################
#
......
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for mod_auth_openidc 2.3.3.
# Generated by GNU Autoconf 2.69 for mod_auth_openidc 2.3.7.
#
# Report bugs to <hans.zandbelt@zmartzone.eu>.
#
......@@ -580,8 +580,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='mod_auth_openidc'
PACKAGE_TARNAME='mod_auth_openidc'
PACKAGE_VERSION='2.3.3'
PACKAGE_STRING='mod_auth_openidc 2.3.3'
PACKAGE_VERSION='2.3.7'
PACKAGE_STRING='mod_auth_openidc 2.3.7'
PACKAGE_BUGREPORT='hans.zandbelt@zmartzone.eu'
PACKAGE_URL=''
......@@ -1269,7 +1269,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures mod_auth_openidc 2.3.3 to adapt to many kinds of systems.
\`configure' configures mod_auth_openidc 2.3.7 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
......@@ -1331,7 +1331,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of mod_auth_openidc 2.3.3:";;
short | recursive ) echo "Configuration of mod_auth_openidc 2.3.7:";;
esac
cat <<\_ACEOF
......@@ -1445,7 +1445,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
mod_auth_openidc configure 2.3.3
mod_auth_openidc configure 2.3.7
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
......@@ -1747,7 +1747,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by mod_auth_openidc $as_me 2.3.3, which was
It was created by mod_auth_openidc $as_me 2.3.7, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
......@@ -2096,7 +2096,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
NAMEVER=mod_auth_openidc-2.3.3
NAMEVER=mod_auth_openidc-2.3.7
# This section defines the --with-apxs2 option.
......@@ -4886,7 +4886,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by mod_auth_openidc $as_me 2.3.3, which was
This file was extended by mod_auth_openidc $as_me 2.3.7, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
......@@ -4939,7 +4939,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
mod_auth_openidc config.status 2.3.3
mod_auth_openidc config.status 2.3.7
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
......
AC_INIT([mod_auth_openidc],[2.3.3],[hans.zandbelt@zmartzone.eu])
AC_INIT([mod_auth_openidc],[2.3.7],[hans.zandbelt@zmartzone.eu])
AC_SUBST(NAMEVER, AC_PACKAGE_TARNAME()-AC_PACKAGE_VERSION())
......
......@@ -18,6 +18,7 @@
*/
/***************************************************************************
* Copyright (C) 2017-2018 ZmartZone IAM
* Copyright (C) 2013-2017 Ping Identity Corporation
* All rights reserved.
*
......
......@@ -18,6 +18,7 @@
*/
/***************************************************************************
* Copyright (C) 2017-2018 ZmartZone IAM
* Copyright (C) 2013-2017 Ping Identity Corporation
* All rights reserved.
*
......@@ -88,8 +89,8 @@ apr_byte_t oidc_cache_mutex_post_config(server_rec *s, oidc_cache_mutex_t *m,
const char *type);
apr_status_t oidc_cache_mutex_child_init(apr_pool_t *p, server_rec *s,
oidc_cache_mutex_t *m);
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_lock(server_rec *s, oidc_cache_mutex_t *m);
apr_byte_t oidc_cache_mutex_unlock(server_rec *s, 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,
......@@ -97,19 +98,21 @@ apr_byte_t oidc_cache_get(request_rec *r, const char *section, const char *key,
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_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_OAUTH_PROVIDER "o"
#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_oauth_provider(r, key, value) oidc_cache_get(r, OIDC_CACHE_SECTION_OAUTH_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)
......@@ -118,6 +121,7 @@ apr_byte_t oidc_cache_set(request_rec *r, const char *section, const char *key,
#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_oauth_provider(r, key, value, expiry) oidc_cache_set(r, OIDC_CACHE_SECTION_OAUTH_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)
......
......@@ -18,6 +18,7 @@
*/
/***************************************************************************
* Copyright (C) 2017-2018 ZmartZone IAM
* Copyright (C) 2013-2017 Ping Identity Corporation
* All rights reserved.
*
......@@ -172,12 +173,12 @@ apr_status_t oidc_cache_mutex_child_init(apr_pool_t *p, server_rec *s,
/*
* global lock
*/
apr_byte_t oidc_cache_mutex_lock(request_rec *r, oidc_cache_mutex_t *m) {
apr_byte_t oidc_cache_mutex_lock(server_rec *s, oidc_cache_mutex_t *m) {
apr_status_t rv = apr_global_mutex_lock(m->mutex);
if (rv != APR_SUCCESS)
oidc_error(r, "apr_global_mutex_lock() failed: %s (%d)",
oidc_serror(s, "apr_global_mutex_lock() failed: %s (%d)",
oidc_cache_status2str(rv), rv);
return TRUE;
......@@ -186,12 +187,12 @@ apr_byte_t oidc_cache_mutex_lock(request_rec *r, oidc_cache_mutex_t *m) {
/*
* global unlock
*/
apr_byte_t oidc_cache_mutex_unlock(request_rec *r, oidc_cache_mutex_t *m) {
apr_byte_t oidc_cache_mutex_unlock(server_rec *s, oidc_cache_mutex_t *m) {
apr_status_t rv = apr_global_mutex_unlock(m->mutex);
if (rv != APR_SUCCESS)
oidc_error(r, "apr_global_mutex_unlock() failed: %s (%d)",
oidc_serror(s, "apr_global_mutex_unlock() failed: %s (%d)",
oidc_cache_status2str(rv), rv);
return TRUE;
......@@ -234,7 +235,7 @@ apr_byte_t oidc_cache_mutex_destroy(server_rec *s, oidc_cache_mutex_t *m) {
#define OIDC_CACHE_CIPHER EVP_aes_256_gcm()
#define OIDC_CACHE_TAG_LEN 16
#if (OPENSSL_VERSION_NUMBER >= 0x10100005L)
#if (OPENSSL_VERSION_NUMBER >= 0x10100005L && !defined(LIBRESSL_VERSION_NUMBER))
#define OIDC_CACHE_CRYPTO_GET_TAG EVP_CTRL_AEAD_GET_TAG
#define OIDC_CACHE_CRYPTO_SET_TAG EVP_CTRL_AEAD_SET_TAG
#define OIDC_CACHE_CRYPTO_SET_IVLEN EVP_CTRL_AEAD_SET_IVLEN
......
......@@ -18,6 +18,7 @@
*/
/***************************************************************************
* Copyright (C) 2017-2018 ZmartZone IAM
* Copyright (C) 2013-2017 Ping Identity Corporation
* All rights reserved.
*
......
......@@ -18,6 +18,7 @@
*/
/***************************************************************************
* Copyright (C) 2017-2018 ZmartZone IAM
* Copyright (C) 2013-2017 Ping Identity Corporation
* All rights reserved.
*
......
This diff is collapsed.
......@@ -18,6 +18,7 @@
*/
/***************************************************************************
* Copyright (C) 2017-2018 ZmartZone IAM
* Copyright (C) 2013-2017 Ping Identity Corporation
* All rights reserved.
*
......@@ -147,9 +148,20 @@ int oidc_cache_shm_child_init(apr_pool_t *p, server_rec *s) {
/*
* assemble single key name based on section/key input
*/
static char *oidc_cache_shm_get_key(apr_pool_t *pool, const char *section,
static char *oidc_cache_shm_get_key(request_rec *r, const char *section,
const char *key) {
return apr_psprintf(pool, "%s:%s", section, key);
char *section_key = apr_psprintf(r->pool, "%s:%s", section, key);
/* check that the passed in key is valid */
if (strlen(section_key) >= OIDC_CACHE_SHM_KEY_MAX) {
oidc_error(r,
"could not construct cache key since key size is too large (%d >= %d) (%s)",
(int )strlen(section_key), OIDC_CACHE_SHM_KEY_MAX, section_key);
return NULL;
}
return section_key;
}
/*
......@@ -163,12 +175,14 @@ static apr_byte_t oidc_cache_shm_get(request_rec *r, const char *section,
oidc_cache_cfg_shm_t *context = (oidc_cache_cfg_shm_t *) cfg->cache_cfg;
int i;
const char *section_key = oidc_cache_shm_get_key(r->pool, section, key);
const char *section_key = oidc_cache_shm_get_key(r, section, key);
if (section_key == NULL)
return FALSE;
*value = NULL;
/* grab the global lock */
if (oidc_cache_mutex_lock(r, context->mutex) == FALSE)
if (oidc_cache_mutex_lock(r->server, context->mutex) == FALSE)
return FALSE;
/* get the pointer to the start of the shared memory block */
......@@ -202,7 +216,7 @@ static apr_byte_t oidc_cache_shm_get(request_rec *r, const char *section,
}
/* release the global lock */
oidc_cache_mutex_unlock(r, context->mutex);
oidc_cache_mutex_unlock(r->server, context->mutex);
return TRUE;
}
......@@ -223,14 +237,9 @@ static apr_byte_t oidc_cache_shm_set(request_rec *r, const char *section,
int i;
apr_time_t age;
const char *section_key = oidc_cache_shm_get_key(r->pool, section, key);
/* check that the passed in key is valid */
if (strlen(section_key) > OIDC_CACHE_SHM_KEY_MAX) {
oidc_error(r, "could not store value since key size is too large (%s)",
section_key);
const char *section_key = oidc_cache_shm_get_key(r, section, key);
if (section_key == NULL)
return FALSE;
}
/* check that the passed in value is valid */
if ((value != NULL)
......@@ -246,7 +255,7 @@ static apr_byte_t oidc_cache_shm_set(request_rec *r, const char *section,
}
/* grab the global lock */
if (oidc_cache_mutex_lock(r, context->mutex) == FALSE)
if (oidc_cache_mutex_lock(r->server, context->mutex) == FALSE)
return FALSE;
/* get a pointer to the shared memory block */
......@@ -319,7 +328,7 @@ static apr_byte_t oidc_cache_shm_set(request_rec *r, const char *section,
}
/* release the global lock */
oidc_cache_mutex_unlock(r, context->mutex);
oidc_cache_mutex_unlock(r->server, context->mutex);
return TRUE;
}
......@@ -331,13 +340,13 @@ static int oidc_cache_shm_destroy(server_rec *s) {
apr_status_t rv = APR_SUCCESS;
if (context->shm) {
apr_global_mutex_lock(context->mutex->mutex);
oidc_cache_mutex_lock(s, context->mutex);
if (*context->mutex->sema == 1) {
rv = apr_shm_destroy(context->shm);
oidc_sdebug(s, "apr_shm_destroy returned: %d", rv);
}
context->shm = NULL;
apr_global_mutex_unlock(context->mutex->mutex);
oidc_cache_mutex_unlock(s, context->mutex);
}
oidc_cache_mutex_destroy(s, context->mutex);
......
......@@ -18,6 +18,7 @@
*/
/***************************************************************************
* Copyright (C) 2017-2018 ZmartZone IAM
* Copyright (C) 2013-2017 Ping Identity Corporation
* All rights reserved.
*
......@@ -254,6 +255,7 @@
#define OIDCProviderMetadataRefreshInterval "OIDCProviderMetadataRefreshInterval"
#define OIDCProviderAuthRequestMethod "OIDCProviderAuthRequestMethod"
#define OIDCBlackListedClaims "OIDCBlackListedClaims"
#define OIDCOAuthServerMetadataURL "OIDCOAuthServerMetadataURL"
extern module AP_MODULE_DECLARE_DATA auth_openidc_module;
......@@ -1047,6 +1049,7 @@ void *oidc_create_server_config(apr_pool_t *pool, server_rec *svr) {
c->provider.auth_request_method = OIDC_DEFAULT_AUTH_REQUEST_METHOD;
c->oauth.ssl_validate_server = OIDC_DEFAULT_SSL_VALIDATE_SERVER;
c->oauth.metadata_url = NULL;
c->oauth.client_id = NULL;
c->oauth.client_secret = NULL;
c->oauth.introspection_endpoint_tls_client_cert = NULL;
......@@ -1316,6 +1319,9 @@ void *oidc_merge_server_config(apr_pool_t *pool, void *BASE, void *ADD) {
add->oauth.ssl_validate_server != OIDC_DEFAULT_SSL_VALIDATE_SERVER ?
add->oauth.ssl_validate_server :
base->oauth.ssl_validate_server;
c->oauth.metadata_url =
add->oauth.metadata_url != NULL ?
add->oauth.metadata_url : base->oauth.metadata_url;
c->oauth.client_id =
add->oauth.client_id != NULL ?
add->oauth.client_id : base->oauth.client_id;
......@@ -1897,13 +1903,26 @@ static int oidc_check_config_openid_openidc(server_rec *s, oidc_cfg *c) {
*/
static int oidc_check_config_oauth(server_rec *s, oidc_cfg *c) {
apr_uri_t r_uri;
if (c->oauth.metadata_url != NULL) {
apr_uri_parse(s->process->pconf, c->oauth.metadata_url, &r_uri);
if ((r_uri.scheme == NULL)
|| (apr_strnatcmp(r_uri.scheme, "https") != 0)) {
oidc_swarn(s,
"the URL scheme (%s) of the configured " OIDCOAuthServerMetadataURL " SHOULD be \"https\" for security reasons!",
r_uri.scheme);
}
return TRUE;
}
if (c->oauth.introspection_endpoint_url == NULL) {
if ((c->oauth.verify_jwks_uri == NULL)
&& (c->oauth.verify_public_keys == NULL)
&& (c->oauth.verify_shared_keys == NULL)) {
oidc_serror(s,
"one of '" OIDCOAuthIntrospectionEndpoint "', '" OIDCOAuthVerifyJwksUri "', '" OIDCOAuthVerifySharedKeys "' or '" OIDCOAuthVerifyCertFiles "' must be set");
"one of '" OIDCOAuthServerMetadataURL "', '" OIDCOAuthIntrospectionEndpoint "', '" OIDCOAuthVerifyJwksUri "', '" OIDCOAuthVerifySharedKeys "' or '" OIDCOAuthVerifyCertFiles "' must be set");
return HTTP_INTERNAL_SERVER_ERROR;
}
......@@ -1935,7 +1954,8 @@ static int oidc_config_check_vhost_config(apr_pool_t *pool, server_rec *s) {
return HTTP_INTERNAL_SERVER_ERROR;
}
if ((cfg->oauth.client_id != NULL) || (cfg->oauth.client_secret != NULL)
if ((cfg->oauth.metadata_url != NULL) || (cfg->oauth.client_id != NULL)
|| (cfg->oauth.client_secret != NULL)
|| (cfg->oauth.introspection_endpoint_url != NULL)
|| (cfg->oauth.verify_jwks_uri != NULL)
|| (cfg->oauth.verify_public_keys != NULL)
......@@ -1982,7 +2002,7 @@ static int oidc_config_merged_vhost_configs_exist(server_rec *s) {
/*
* SSL initialization magic copied from mod_auth_cas
*/
#if defined(OPENSSL_THREADS) && APR_HAS_THREADS
#if ((OPENSSL_VERSION_NUMBER < 0x10100000) && defined(OPENSSL_THREADS) && APR_HAS_THREADS)
static apr_thread_mutex_t **ssl_locks;
static int ssl_num_locks;
......@@ -2037,7 +2057,7 @@ static apr_status_t oidc_cleanup_parent(void *data) {
oidc_cleanup_child(data);
#if (defined (OPENSSL_THREADS) && APR_HAS_THREADS)
#if ((OPENSSL_VERSION_NUMBER < 0x10100000) && defined (OPENSSL_THREADS) && APR_HAS_THREADS)
if (CRYPTO_get_locking_callback() == oidc_ssl_locking_callback)
CRYPTO_set_locking_callback(NULL);
#ifdef OPENSSL_NO_THREADID
......@@ -2048,7 +2068,8 @@ static apr_status_t oidc_cleanup_parent(void *data) {
CRYPTO_THREADID_set_callback(NULL);
#endif /* OPENSSL_NO_THREADID */
#endif /* defined(OPENSSL_THREADS) && APR_HAS_THREADS */
#endif /* (OPENSSL_VERSION_NUMBER < 0x10100000) && defined (OPENSSL_THREADS) && APR_HAS_THREADS */
EVP_cleanup();
curl_global_cleanup();
......@@ -2065,7 +2086,6 @@ static int oidc_post_config(apr_pool_t *pool, apr_pool_t *p1, apr_pool_t *p2,
server_rec *s) {
const char *userdata_key = "oidc_post_config";
void *data = NULL;