1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 /***************************************************************************
21  * Copyright (C) 2017-2021 ZmartZone Holding BV
22  * Copyright (C) 2013-2017 Ping Identity Corporation
23  * All rights reserved.
24  *
25  * DISCLAIMER OF WARRANTIES:
26  *
27  * THE SOFTWARE PROVIDED HEREUNDER IS PROVIDED ON AN "AS IS" BASIS, WITHOUT
28  * ANY WARRANTIES OR REPRESENTATIONS EXPRESS, IMPLIED OR STATUTORY; INCLUDING,
29  * WITHOUT LIMITATION, WARRANTIES OF QUALITY, PERFORMANCE, NONINFRINGEMENT,
30  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  NOR ARE THERE ANY
31  * WARRANTIES CREATED BY A COURSE OR DEALING, COURSE OF PERFORMANCE OR TRADE
32  * USAGE.  FURTHERMORE, THERE ARE NO WARRANTIES THAT THE SOFTWARE WILL MEET
33  * YOUR NEEDS OR BE FREE FROM ERRORS, OR THAT THE OPERATION OF THE SOFTWARE
34  * WILL BE UNINTERRUPTED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
35  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
36  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES HOWEVER CAUSED AND ON ANY THEORY OF
37  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
38  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
39  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40  *
41  * @Author: Hans Zandbelt - hans.zandbelt@zmartzone.eu
42  */
43 
44 #include <apr.h>
45 #include <apr_errno.h>
46 #include <apr_strings.h>
47 #include <apr_portable.h>
48 #include <apr_base64.h>
49 
50 #include <httpd.h>
51 #include <http_config.h>
52 #include <http_log.h>
53 #include <http_request.h>
54 #include <ap_provider.h>
55 
56 #include <curl/curl.h>
57 
58 #include "mod_auth_openidc.h"
59 #include "parse.h"
60 
61 #define OPENSSL_THREAD_DEFINES
62 #include <openssl/opensslconf.h>
63 #include <openssl/opensslv.h>
64 #include <openssl/evp.h>
65 #if (OPENSSL_VERSION_NUMBER < 0x01000000)
66 #define OPENSSL_NO_THREADID
67 #endif
68 
69 /* validate SSL server certificates by default */
70 #define OIDC_DEFAULT_SSL_VALIDATE_SERVER 1
71 /* validate issuer by default */
72 #define OIDC_DEFAULT_VALIDATE_ISSUER 1
73 /* default scope requested from the OP */
74 #define OIDC_DEFAULT_SCOPE "openid"
75 /* default claim delimiter for multi-valued claims passed in a HTTP header */
76 #define OIDC_DEFAULT_CLAIM_DELIMITER ","
77 /* default prefix for claim names being passed in HTTP headers */
78 #define OIDC_DEFAULT_CLAIM_PREFIX "OIDC_CLAIM_"
79 /* default name for the claim that will contain the REMOTE_USER value for OpenID Connect protected paths */
80 #define OIDC_DEFAULT_CLAIM_REMOTE_USER "sub@"
81 /* default name for the claim that will contain the REMOTE_USER value for OAuth 2.0 protected paths */
82 #define OIDC_DEFAULT_OAUTH_CLAIM_REMOTE_USER "sub"
83 /* default name of the session cookie */
84 #define OIDC_DEFAULT_COOKIE "mod_auth_openidc_session"
85 /* default for the HTTP header name in which the remote user name is passed */
86 #define OIDC_DEFAULT_AUTHN_HEADER NULL
87 /* default client_name the client uses for dynamic client registration */
88 #define OIDC_DEFAULT_CLIENT_NAME "OpenID Connect Apache Module (mod_auth_openidc)"
89 /* timeouts in seconds for HTTP calls that may take a long time */
90 #define OIDC_DEFAULT_HTTP_TIMEOUT_LONG  60
91 /* timeouts in seconds for HTTP calls that should take a short time (registry/discovery related) */
92 #define OIDC_DEFAULT_HTTP_TIMEOUT_SHORT  5
93 /* default session storage type */
94 #define OIDC_DEFAULT_SESSION_TYPE OIDC_SESSION_TYPE_SERVER_CACHE
95 /* default client-cookie chunking size */
96 #define OIDC_DEFAULT_SESSION_CLIENT_COOKIE_CHUNK_SIZE 4000
97 /* timeout in seconds after which state expires */
98 #define OIDC_DEFAULT_STATE_TIMEOUT 300
99 /* maximum number of parallel state cookies; 0 means unlimited, until the browser or server gives up */
100 #define OIDC_DEFAULT_MAX_NUMBER_OF_STATE_COOKIES 7
101 /* default setting for deleting the oldest state cookies */
102 #define OIDC_DEFAULT_DELETE_OLDEST_STATE_COOKIES 0
103 /* default session inactivity timeout */
104 #define OIDC_DEFAULT_SESSION_INACTIVITY_TIMEOUT 300
105 /* default session max duration */
106 #define OIDC_DEFAULT_SESSION_MAX_DURATION 3600 * 8
107 /* default OpenID Connect authorization response type */
108 #define OIDC_DEFAULT_RESPONSE_TYPE OIDC_PROTO_CODE
109 /* default duration in seconds after which retrieved JWS should be refreshed */
110 #define OIDC_DEFAULT_JWKS_REFRESH_INTERVAL 3600
111 /* default max cache size for shm */
112 #define OIDC_DEFAULT_CACHE_SHM_SIZE 500
113 /* default max cache entry size for shm: # value + # key + # overhead */
114 #define OIDC_DEFAULT_CACHE_SHM_ENTRY_SIZE_MAX 16384 + 512 + 17
115 /* minimum size of a cache entry */
116 #define OIDC_MINIMUM_CACHE_SHM_ENTRY_SIZE_MAX 8192 + 512 + 17
117 /* for issued-at timestamp (iat) checking */
118 #define OIDC_DEFAULT_IDTOKEN_IAT_SLACK 600
119 /* for file-based caching: clean interval in seconds */
120 #define OIDC_DEFAULT_CACHE_FILE_CLEAN_INTERVAL 60
121 /* set httponly flag on cookies */
122 #define OIDC_DEFAULT_COOKIE_HTTPONLY 1
123 /* set Same-Site flag on cookies */
124 #define OIDC_DEFAULT_COOKIE_SAME_SITE 0
125 /* default cookie path */
126 #define OIDC_DEFAULT_COOKIE_PATH "/"
127 /* default OAuth 2.0 introspection token parameter name */
128 #define OIDC_DEFAULT_OAUTH_TOKEN_PARAM_NAME "token"
129 /* default OAuth 2.0 introspection call HTTP method */
130 #define OIDC_DEFAULT_OAUTH_ENDPOINT_METHOD OIDC_INTROSPECTION_METHOD_POST
131 /* default OAuth 2.0 non-spec compliant introspection expiry claim name */
132 #define OIDC_DEFAULT_OAUTH_EXPIRY_CLAIM_NAME OIDC_PROTO_EXPIRES_IN
133 /* default OAuth 2.0 non-spec compliant introspection expiry claim format */
134 #define OIDC_DEFAULT_OAUTH_EXPIRY_CLAIM_FORMAT OIDC_CLAIM_FORMAT_RELATIVE
135 /* default OAuth 2.0 non-spec compliant introspection expiry claim required */
136 #define OIDC_DEFAULT_OAUTH_EXPIRY_CLAIM_REQUIRED TRUE
137 /* default refresh interval in seconds after which claims from the user info endpoint should be refreshed */
138 #define OIDC_DEFAULT_USERINFO_REFRESH_INTERVAL 0
139 /* default for preserving POST parameters across authentication requests */
140 #define OIDC_DEFAULT_PRESERVE_POST 0
141 /* default for passing the access token in a header/environment variable */
142 #define OIDC_DEFAULT_PASS_REFRESH_TOKEN 0
143 /* default for passing app info in headers */
144 #define OIDC_DEFAULT_PASS_APP_INFO_IN_HEADERS 1
145 /* default for passing app info in environment variables */
146 #define OIDC_DEFAULT_PASS_APP_INFO_IN_ENVVARS 1
147 /* default for passing app info in base64 encoded format */
148 #define OIDC_DEFAULT_PASS_APP_INFO_BASE64URL 0
149 /* default value for the token introspection interval (0 = disabled, no expiry of claims) */
150 #define OIDC_DEFAULT_TOKEN_INTROSPECTION_INTERVAL 0
151 /* default action to take on an incoming unauthenticated request */
152 #define OIDC_DEFAULT_UNAUTH_ACTION OIDC_UNAUTH_AUTHENTICATE
153 /* default action to take on an incoming authorized request */
154 #define OIDC_DEFAULT_UNAUTZ_ACTION OIDC_UNAUTZ_RETURN403
155 /* defines for how long provider metadata will be cached */
156 #define OIDC_DEFAULT_PROVIDER_METADATA_REFRESH_INTERVAL 0
157 /* defines the default token binding policy for a provider */
158 #define OIDC_DEFAULT_PROVIDER_TOKEN_BINDING_POLICY OIDC_TOKEN_BINDING_POLICY_OPTIONAL
159 /* defines the default token binding policy for OAuth 2.0 access tokens */
160 #define OIDC_DEFAULT_OAUTH_ACCESS_TOKEN_BINDING_POLICY OIDC_TOKEN_BINDING_POLICY_OPTIONAL
161 /* define the default HTTP method used to send the authentication request to the provider */
162 #define OIDC_DEFAULT_AUTH_REQUEST_METHOD OIDC_AUTH_REQUEST_METHOD_GET
163 /* define whether the issuer will be added to the redirect uri by default to mitigate the IDP mixup attack */
164 #define OIDC_DEFAULT_PROVIDER_ISSUER_SPECIFIC_REDIRECT_URI 0
165 /* define the default number of seconds that the access token needs to be valid for; -1 = no refresh */
166 #define OIDC_DEFAULT_REFRESH_ACCESS_TOKEN_BEFORE_EXPIRY -1
167 /* default setting for calculating the fingerprint of the state from request headers during authentication */
168 #define OIDC_DEFAULT_STATE_INPUT_HEADERS (OIDC_STATE_INPUT_HEADERS_USER_AGENT | OIDC_STATE_INPUT_HEADERS_X_FORWARDED_FOR)
169 /* default prefix of the state cookie that binds the state in the authorization request/response to the browser */
170 #define OIDC_DEFAULT_STATE_COOKIE_PREFIX "mod_auth_openidc_state_"
171 
172 #define OIDCProviderMetadataURL                "OIDCProviderMetadataURL"
173 #define OIDCProviderIssuer                     "OIDCProviderIssuer"
174 #define OIDCProviderAuthorizationEndpoint      "OIDCProviderAuthorizationEndpoint"
175 #define OIDCProviderTokenEndpoint              "OIDCProviderTokenEndpoint"
176 #define OIDCProviderTokenEndpointAuth          "OIDCProviderTokenEndpointAuth"
177 #define OIDCProviderTokenEndpointParams        "OIDCProviderTokenEndpointParams"
178 #define OIDCProviderRegistrationEndpointJson   "OIDCProviderRegistrationEndpointJson"
179 #define OIDCProviderUserInfoEndpoint           "OIDCProviderUserInfoEndpoint"
180 #define OIDCProviderRevocationEndpoint         "OIDCProviderRevocationEndpoint"
181 #define OIDCProviderCheckSessionIFrame         "OIDCProviderCheckSessionIFrame"
182 #define OIDCProviderEndSessionEndpoint         "OIDCProviderEndSessionEndpoint"
183 #define OIDCProviderBackChannelLogoutSupported "OIDCProviderBackChannelLogoutSupported"
184 #define OIDCProviderJwksUri                    "OIDCProviderJwksUri"
185 #define OIDCResponseType                       "OIDCResponseType"
186 #define OIDCResponseMode                       "OIDCResponseMode"
187 #define OIDCPublicKeyFiles                     "OIDCPublicKeyFiles"
188 #define OIDCClientJwksUri                      "OIDCClientJwksUri"
189 #define OIDCIDTokenSignedResponseAlg           "OIDCIDTokenSignedResponseAlg"
190 #define OIDCIDTokenEncryptedResponseAlg        "OIDCIDTokenEncryptedResponseAlg"
191 #define OIDCIDTokenEncryptedResponseEnc        "OIDCIDTokenEncryptedResponseEnc"
192 #define OIDCUserInfoSignedResponseAlg          "OIDCUserInfoSignedResponseAlg"
193 #define OIDCUserInfoEncryptedResponseAlg       "OIDCUserInfoEncryptedResponseAlg"
194 #define OIDCUserInfoEncryptedResponseEnc       "OIDCUserInfoEncryptedResponseEnc"
195 #define OIDCUserInfoTokenMethod                "OIDCUserInfoTokenMethod"
196 #define OIDCTokenBindingPolicy                 "OIDCTokenBindingPolicy"
197 #define OIDCSSLValidateServer                  "OIDCSSLValidateServer"
198 #define OIDCValidateIssuer                     "OIDCValidateIssuer"
199 #define OIDCClientName                         "OIDCClientName"
200 #define OIDCClientContact                      "OIDCClientContact"
201 #define OIDCScope                              "OIDCScope"
202 #define OIDCPathScope                          "OIDCPathScope"
203 #define OIDCJWKSRefreshInterval                "OIDCJWKSRefreshInterval"
204 #define OIDCIDTokenIatSlack                    "OIDCIDTokenIatSlack"
205 #define OIDCSessionMaxDuration                 "OIDCSessionMaxDuration"
206 #define OIDCAuthRequestParams                  "OIDCAuthRequestParams"
207 #define OIDCPathAuthRequestParams              "OIDCPathAuthRequestParams"
208 #define OIDCPKCEMethod                         "OIDCPKCEMethod"
209 #define OIDCClientID                           "OIDCClientID"
210 #define OIDCClientSecret                       "OIDCClientSecret"
211 #define OIDCClientTokenEndpointCert            "OIDCClientTokenEndpointCert"
212 #define OIDCClientTokenEndpointKey             "OIDCClientTokenEndpointKey"
213 #define OIDCDefaultLoggedOutURL                "OIDCDefaultLoggedOutURL"
214 #define OIDCCookieHTTPOnly                     "OIDCCookieHTTPOnly"
215 #define OIDCCookieSameSite                     "OIDCCookieSameSite"
216 #define OIDCOutgoingProxy                      "OIDCOutgoingProxy"
217 #define OIDCCryptoPassphrase                   "OIDCCryptoPassphrase"
218 #define OIDCClaimDelimiter                     "OIDCClaimDelimiter"
219 #define OIDCPassIDTokenAs                      "OIDCPassIDTokenAs"
220 #define OIDCPassUserInfoAs                     "OIDCPassUserInfoAs"
221 #define OIDCOAuthClientID                      "OIDCOAuthClientID"
222 #define OIDCOAuthClientSecret                  "OIDCOAuthClientSecret"
223 #define OIDCOAuthIntrospectionClientAuthBearerToken "OIDCOAuthIntrospectionClientAuthBearerToken"
224 #define OIDCOAuthIntrospectionEndpoint         "OIDCOAuthIntrospectionEndpoint"
225 #define OIDCOAuthIntrospectionEndpointMethod   "OIDCOAuthIntrospectionEndpointMethod"
226 #define OIDCOAuthIntrospectionEndpointParams   "OIDCOAuthIntrospectionEndpointParams"
227 #define OIDCOAuthIntrospectionEndpointAuth     "OIDCOAuthIntrospectionEndpointAuth"
228 #define OIDCOAuthIntrospectionEndpointCert     "OIDCOAuthIntrospectionEndpointCert"
229 #define OIDCOAuthIntrospectionEndpointKey      "OIDCOAuthIntrospectionEndpointKey"
230 #define OIDCOAuthIntrospectionTokenParamName   "OIDCOAuthIntrospectionTokenParamName"
231 #define OIDCOAuthTokenExpiryClaim              "OIDCOAuthTokenExpiryClaim"
232 #define OIDCOAuthSSLValidateServer             "OIDCOAuthSSLValidateServer"
233 #define OIDCOAuthVerifyCertFiles               "OIDCOAuthVerifyCertFiles"
234 #define OIDCOAuthVerifySharedKeys              "OIDCOAuthVerifySharedKeys"
235 #define OIDCOAuthVerifyJwksUri                 "OIDCOAuthVerifyJwksUri"
236 #define OIDCHTTPTimeoutLong                    "OIDCHTTPTimeoutLong"
237 #define OIDCHTTPTimeoutShort                   "OIDCHTTPTimeoutShort"
238 #define OIDCStateTimeout                       "OIDCStateTimeout"
239 #define OIDCStateMaxNumberOfCookies            "OIDCStateMaxNumberOfCookies"
240 #define OIDCSessionInactivityTimeout           "OIDCSessionInactivityTimeout"
241 #define OIDCMetadataDir                        "OIDCMetadataDir"
242 #define OIDCSessionCacheFallbackToCookie       "OIDCSessionCacheFallbackToCookie"
243 #define OIDCSessionCookieChunkSize             "OIDCSessionCookieChunkSize"
244 #define OIDCScrubRequestHeaders                "OIDCScrubRequestHeaders"
245 #define OIDCCacheType                          "OIDCCacheType"
246 #define OIDCCacheEncrypt                       "OIDCCacheEncrypt"
247 #define OIDCCacheDir                           "OIDCCacheDir"
248 #define OIDCCacheFileCleanInterval             "OIDCCacheFileCleanInterval"
249 #define OIDCRedisCachePassword                 "OIDCRedisCachePassword"
250 #define OIDCRedisCacheDatabase                 "OIDCRedisCacheDatabase"
251 #define OIDCHTMLErrorTemplate                  "OIDCHTMLErrorTemplate"
252 #define OIDCDiscoverURL                        "OIDCDiscoverURL"
253 #define OIDCPassCookies                        "OIDCPassCookies"
254 #define OIDCStripCookies                       "OIDCStripCookies"
255 #define OIDCAuthNHeader                        "OIDCAuthNHeader"
256 #define OIDCCookie                             "OIDCCookie"
257 #define OIDCUnAuthAction                       "OIDCUnAuthAction"
258 #define OIDCUnAutzAction                       "OIDCUnAutzAction"
259 #define OIDCPassClaimsAs                       "OIDCPassClaimsAs"
260 #define OIDCOAuthAcceptTokenAs                 "OIDCOAuthAcceptTokenAs"
261 #define OIDCUserInfoRefreshInterval            "OIDCUserInfoRefreshInterval"
262 #define OIDCOAuthTokenIntrospectionInterval    "OIDCOAuthTokenIntrospectionInterval"
263 #define OIDCPreservePost                       "OIDCPreservePost"
264 #define OIDCPassRefreshToken                   "OIDCPassRefreshToken"
265 #define OIDCRequestObject                      "OIDCRequestObject"
266 #define OIDCProviderMetadataRefreshInterval    "OIDCProviderMetadataRefreshInterval"
267 #define OIDCProviderAuthRequestMethod          "OIDCProviderAuthRequestMethod"
268 #define OIDCBlackListedClaims                  "OIDCBlackListedClaims"
269 #define OIDCOAuthServerMetadataURL             "OIDCOAuthServerMetadataURL"
270 #define OIDCOAuthAccessTokenBindingPolicy      "OIDCOAuthAccessTokenBindingPolicy"
271 #define OIDCRefreshAccessTokenBeforeExpiry     "OIDCRefreshAccessTokenBeforeExpiry"
272 #define OIDCStateInputHeaders                  "OIDCStateInputHeaders"
273 #define OIDCRedirectURLsAllowed                "OIDCRedirectURLsAllowed"
274 #define OIDCStateCookiePrefix                  "OIDCStateCookiePrefix"
275 #define OIDCCABundlePath                       "OIDCCABundlePath"
276 
277 extern module AP_MODULE_DECLARE_DATA auth_openidc_module;
278 
279 /*
280  * directory related configuration
281  */
282 typedef struct oidc_dir_cfg {
283 	char *discover_url;
284 	char *cookie_path;
285 	char *cookie;
286 	char *authn_header;
287 	int unauth_action;
288 #if MODULE_MAGIC_NUMBER_MAJOR >= 20100714
289 	ap_expr_info_t *unauth_expression;
290 #endif
291 	int unautz_action;
292 	apr_array_header_t *pass_cookies;
293 	apr_array_header_t *strip_cookies;
294 	int pass_info_in_headers;
295 	int pass_info_in_env_vars;
296 	int pass_info_base64url;
297 	int oauth_accept_token_in;
298 	apr_hash_t *oauth_accept_token_options;
299 	int oauth_token_introspect_interval;
300 	int preserve_post;
301 	int pass_refresh_token;
302 	char *path_auth_request_params;
303 	char *path_scope;
304 	int refresh_access_token_before_expiry;
305 	int logout_on_error_refresh;
306 	char *state_cookie_prefix;
307 } oidc_dir_cfg;
308 
309 #define OIDC_CONFIG_DIR_RV(cmd, rv) rv != NULL ? apr_psprintf(cmd->pool, "Invalid value for directive '%s': %s", cmd->directive->directive, rv) : NULL
310 
311 /*
312  * set a boolean value in the server config
313  */
oidc_set_flag_slot(cmd_parms * cmd,void * struct_ptr,int arg)314 static const char* oidc_set_flag_slot(cmd_parms *cmd, void *struct_ptr, int arg) {
315 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
316 			&auth_openidc_module);
317 	return ap_set_flag_slot(cmd, cfg, arg);
318 }
319 
320 /*
321  * set a string value in the server config
322  */
oidc_set_string_slot(cmd_parms * cmd,void * struct_ptr,const char * arg)323 static const char* oidc_set_string_slot(cmd_parms *cmd, void *struct_ptr,
324 		const char *arg) {
325 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
326 			&auth_openidc_module);
327 	return ap_set_string_slot(cmd, cfg, arg);
328 }
329 
330 /*
331  * set an integer value in the server config
332  */
oidc_set_int_slot(cmd_parms * cmd,void * struct_ptr,const char * arg)333 static const char* oidc_set_int_slot(cmd_parms *cmd, void *struct_ptr,
334 		const char *arg) {
335 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
336 			&auth_openidc_module);
337 	return ap_set_int_slot(cmd, cfg, arg);
338 }
339 
340 /*
341  * set a URL value in a config record
342  */
oidc_set_url_slot_type(cmd_parms * cmd,void * ptr,const char * arg,const char * type)343 static const char* oidc_set_url_slot_type(cmd_parms *cmd, void *ptr,
344 		const char *arg, const char *type) {
345 	const char *rv =
346 			type != NULL ?
347 					oidc_valid_url(cmd->pool, arg, type) :
348 					oidc_valid_http_url(cmd->pool, arg);
349 	if (rv == NULL)
350 		rv = ap_set_string_slot(cmd, ptr, arg);
351 	return rv;
352 }
353 
354 /*
355  * set a HTTPS value in the server config
356  */
oidc_set_https_slot(cmd_parms * cmd,void * ptr,const char * arg)357 static const char* oidc_set_https_slot(cmd_parms *cmd, void *ptr,
358 		const char *arg) {
359 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
360 			&auth_openidc_module);
361 	return oidc_set_url_slot_type(cmd, cfg, arg, "https");
362 }
363 
364 /*
365  * set a HTTPS/HTTP value in the server config
366  */
oidc_set_url_slot(cmd_parms * cmd,void * ptr,const char * arg)367 static const char* oidc_set_url_slot(cmd_parms *cmd, void *ptr, const char *arg) {
368 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
369 			&auth_openidc_module);
370 	return oidc_set_url_slot_type(cmd, cfg, arg, NULL);
371 }
372 
373 /*
374  * set a relative or absolute URL value in a config rec
375  */
oidc_set_relative_or_absolute_url_slot_dir_cfg(cmd_parms * cmd,void * ptr,const char * arg)376 static const char* oidc_set_relative_or_absolute_url_slot_dir_cfg(
377 		cmd_parms *cmd, void *ptr, const char *arg) {
378 	if (arg[0] == OIDC_CHAR_FORWARD_SLASH) {
379 		// relative uri
380 		apr_uri_t uri;
381 		if (apr_uri_parse(cmd->pool, arg, &uri) != APR_SUCCESS) {
382 			const char *rv = apr_psprintf(cmd->pool,
383 					"cannot parse '%s' as relative URI", arg);
384 			return OIDC_CONFIG_DIR_RV(cmd, rv);
385 		} else {
386 			return ap_set_string_slot(cmd, ptr, arg);
387 		}
388 	} else {
389 		// absolute uri
390 		return oidc_set_url_slot_type(cmd, ptr, arg, NULL);
391 	}
392 }
393 
394 /*
395  * set a relative or absolute URL value in the server config
396  */
oidc_set_relative_or_absolute_url_slot(cmd_parms * cmd,void * ptr,const char * arg)397 static const char* oidc_set_relative_or_absolute_url_slot(cmd_parms *cmd,
398 		void *ptr, const char *arg) {
399 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
400 			&auth_openidc_module);
401 	return oidc_set_relative_or_absolute_url_slot_dir_cfg(cmd, cfg, arg);
402 }
403 
404 /*
405  * set a directory value in the server config
406  */
407 // TODO: it's not really a syntax error... (could be fixed at runtime but then we'd have to restart the server)
oidc_set_dir_slot(cmd_parms * cmd,void * ptr,const char * arg)408 static const char* oidc_set_dir_slot(cmd_parms *cmd, void *ptr, const char *arg) {
409 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
410 			&auth_openidc_module);
411 	const char *rv = oidc_valid_dir(cmd->pool, arg);
412 	if (rv == NULL)
413 		rv = ap_set_string_slot(cmd, cfg, arg);
414 	return rv;
415 }
416 
417 /*
418  * set a path value in the server config, converting to absolute if necessary
419  */
oidc_set_path_slot(cmd_parms * cmd,void * ptr,const char * arg)420 static const char* oidc_set_path_slot(cmd_parms *cmd, void *ptr,
421 		const char *arg) {
422 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
423 			&auth_openidc_module);
424 	const char *full_path = oidc_util_get_full_path(cmd->pool, arg);
425 	return ap_set_string_slot(cmd, cfg, full_path);
426 }
427 
428 /*
429  * set a string value in the server config with exec support
430  */
oidc_set_passphrase_slot(cmd_parms * cmd,void * struct_ptr,const char * arg)431 static const char* oidc_set_passphrase_slot(cmd_parms *cmd, void *struct_ptr,
432 		const char *arg) {
433 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
434 			&auth_openidc_module);
435 	const char *passphrase = NULL;
436 #if MODULE_MAGIC_NUMBER_MAJOR >= 20100714
437 	int arglen = strlen(arg);
438 	char **argv = NULL;
439 	char *result = NULL;
440 	/* Based on code from mod_session_crypto. */
441 	if (arglen > 5 && strncmp(arg, "exec:", 5) == 0) {
442 		if (apr_tokenize_to_argv(arg + 5, &argv, cmd->temp_pool) != APR_SUCCESS) {
443 			return apr_pstrcat(cmd->pool,
444 					"Unable to parse exec arguments from ", arg + 5, NULL);
445 		}
446 		argv[0] = ap_server_root_relative(cmd->temp_pool, argv[0]);
447 		if (!argv[0]) {
448 			return apr_pstrcat(cmd->pool, "Invalid ", cmd->cmd->name,
449 					" exec location:", arg + 5, NULL);
450 		}
451 		result = ap_get_exec_line(cmd->pool, argv[0],
452 				(const char* const*) argv);
453 		if (!result) {
454 			return apr_pstrcat(cmd->pool,
455 					"Unable to get passphrase from exec of ", arg + 5, NULL);
456 		}
457 		passphrase = result;
458 	} else {
459 		passphrase = arg;
460 	}
461 #else
462 	passphrase = arg;
463 #endif
464 
465 	return ap_set_string_slot(cmd, cfg, passphrase);
466 }
467 
468 /*
469  * set the cookie domain in the server config and check it syntactically
470  */
oidc_set_cookie_domain(cmd_parms * cmd,void * ptr,const char * value)471 static const char* oidc_set_cookie_domain(cmd_parms *cmd, void *ptr,
472 		const char *value) {
473 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
474 			&auth_openidc_module);
475 	const char *rv = oidc_valid_cookie_domain(cmd->pool, value);
476 	if (rv == NULL)
477 		cfg->cookie_domain = apr_pstrdup(cmd->pool, value);
478 	return OIDC_CONFIG_DIR_RV(cmd, rv);
479 }
480 
481 /*
482  * set the session storage type
483  */
oidc_set_session_type(cmd_parms * cmd,void * ptr,const char * arg)484 static const char* oidc_set_session_type(cmd_parms *cmd, void *ptr,
485 		const char *arg) {
486 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
487 			&auth_openidc_module);
488 	const char *rv = oidc_parse_session_type(cmd->pool, arg, &cfg->session_type,
489 			&cfg->persistent_session_cookie);
490 	return OIDC_CONFIG_DIR_RV(cmd, rv);
491 }
492 
493 /*
494  * set the maximum size of a shared memory cache entry and enforces a minimum
495  */
oidc_set_cache_shm_entry_size_max(cmd_parms * cmd,void * ptr,const char * arg)496 static const char* oidc_set_cache_shm_entry_size_max(cmd_parms *cmd, void *ptr,
497 		const char *arg) {
498 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
499 			&auth_openidc_module);
500 	const char *rv = oidc_parse_cache_shm_entry_size_max(cmd->pool, arg,
501 			&cfg->cache_shm_entry_size_max);
502 	return OIDC_CONFIG_DIR_RV(cmd, rv);
503 }
504 
505 /*
506  * set the cache type
507  */
oidc_set_cache_type(cmd_parms * cmd,void * ptr,const char * arg)508 static const char* oidc_set_cache_type(cmd_parms *cmd, void *ptr,
509 		const char *arg) {
510 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
511 			&auth_openidc_module);
512 	const char *rv = oidc_parse_cache_type(cmd->pool, arg, &cfg->cache);
513 	return OIDC_CONFIG_DIR_RV(cmd, rv);
514 }
515 
516 /*
517  * set SSL validation slot
518  */
oidc_set_ssl_validate_slot(cmd_parms * cmd,void * struct_ptr,const char * arg)519 static const char* oidc_set_ssl_validate_slot(cmd_parms *cmd, void *struct_ptr,
520 		const char *arg) {
521 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
522 			&auth_openidc_module);
523 	int b = 0;
524 	const char *rv = oidc_parse_boolean(cmd->pool, arg, &b);
525 	if (rv == NULL)
526 		rv = ap_set_flag_slot(cmd, cfg, b);
527 	return OIDC_CONFIG_DIR_RV(cmd, rv);
528 }
529 
530 /*
531  * set validate issuer slot
532  */
oidc_set_validate_issuer_slot(cmd_parms * cmd,void * struct_ptr,const char * arg)533 static const char* oidc_set_validate_issuer_slot(cmd_parms *cmd,
534 		void *struct_ptr, const char *arg) {
535 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
536 			&auth_openidc_module);
537 	int b = 0;
538 	const char *rv = oidc_parse_boolean(cmd->pool, arg, &b);
539 	if (rv == NULL)
540 		rv = ap_set_flag_slot(cmd, cfg, b);
541 	return OIDC_CONFIG_DIR_RV(cmd, rv);
542 }
543 
544 /*
545  * return the right token endpoint authentication method validation function, based on whether private keys are set
546  */
oidc_cfg_get_valid_endpoint_auth_function(oidc_cfg * cfg)547 oidc_valid_function_t oidc_cfg_get_valid_endpoint_auth_function(oidc_cfg *cfg) {
548 	return (cfg->private_keys != NULL) ?
549 			oidc_valid_endpoint_auth_method :
550 			oidc_valid_endpoint_auth_method_no_private_key;
551 }
552 
553 /*
554  * set an authentication method for an endpoint and check it is one that we support
555  */
oidc_set_endpoint_auth_slot(cmd_parms * cmd,void * struct_ptr,const char * arg)556 static const char* oidc_set_endpoint_auth_slot(cmd_parms *cmd, void *struct_ptr,
557 		const char *arg) {
558 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
559 			&auth_openidc_module);
560 	const char *rv = oidc_cfg_get_valid_endpoint_auth_function(cfg)(cmd->pool,
561 			arg);
562 	if (rv == NULL)
563 		rv = ap_set_string_slot(cmd, cfg, arg);
564 	return OIDC_CONFIG_DIR_RV(cmd, rv);
565 }
566 
567 /*
568  * set the response type used
569  */
oidc_set_response_type(cmd_parms * cmd,void * struct_ptr,const char * arg)570 static const char* oidc_set_response_type(cmd_parms *cmd, void *struct_ptr,
571 		const char *arg) {
572 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
573 			&auth_openidc_module);
574 
575 	const char *rv = oidc_valid_response_type(cmd->pool, arg);
576 	if (rv == NULL)
577 		rv = ap_set_string_slot(cmd, cfg, arg);
578 	return OIDC_CONFIG_DIR_RV(cmd, rv);
579 }
580 
oidc_parse_pkce_type(apr_pool_t * pool,const char * arg,oidc_proto_pkce_t ** type)581 const char* oidc_parse_pkce_type(apr_pool_t *pool, const char *arg,
582 		oidc_proto_pkce_t **type) {
583 	const char *rv = oidc_valid_pkce_method(pool, arg);
584 	if (rv != NULL)
585 		return rv;
586 
587 	if (apr_strnatcmp(arg, OIDC_PKCE_METHOD_PLAIN) == 0) {
588 		*type = &oidc_pkce_plain;
589 	} else if (apr_strnatcmp(arg, OIDC_PKCE_METHOD_S256) == 0) {
590 		*type = &oidc_pkce_s256;
591 	} else if (apr_strnatcmp(arg, OIDC_PKCE_METHOD_REFERRED_TB) == 0) {
592 		*type = &oidc_pkce_referred_tb;
593 	}
594 
595 	return NULL;
596 }
597 
598 /*
599  * define the PCKE method to use
600  */
oidc_set_pkce_method(cmd_parms * cmd,void * ptr,const char * arg)601 static const char* oidc_set_pkce_method(cmd_parms *cmd, void *ptr,
602 		const char *arg) {
603 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
604 			&auth_openidc_module);
605 	const char *rv = oidc_parse_pkce_type(cmd->pool, arg, &cfg->provider.pkce);
606 	return OIDC_CONFIG_DIR_RV(cmd, rv);
607 }
608 
609 /*
610  * set the response mode used
611  */
oidc_set_response_mode(cmd_parms * cmd,void * struct_ptr,const char * arg)612 static const char* oidc_set_response_mode(cmd_parms *cmd, void *struct_ptr,
613 		const char *arg) {
614 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
615 			&auth_openidc_module);
616 
617 	const char *rv = oidc_valid_response_mode(cmd->pool, arg);
618 	if (rv == NULL)
619 		rv = ap_set_string_slot(cmd, cfg, arg);
620 	return OIDC_CONFIG_DIR_RV(cmd, rv);
621 }
622 
623 /*
624  * set the signing algorithm to be used by the OP (id_token/user_info)
625  */
oidc_set_signed_response_alg(cmd_parms * cmd,void * struct_ptr,const char * arg)626 static const char* oidc_set_signed_response_alg(cmd_parms *cmd,
627 		void *struct_ptr, const char *arg) {
628 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
629 			&auth_openidc_module);
630 	const char *rv = oidc_valid_signed_response_alg(cmd->pool, arg);
631 	if (rv == NULL)
632 		rv = ap_set_string_slot(cmd, cfg, arg);
633 	return OIDC_CONFIG_DIR_RV(cmd, rv);
634 }
635 
636 /*
637  * set the Content Encryption Key encryption algorithm to be used by the OP (id_token/user_info)
638  */
oidc_set_encrypted_response_alg(cmd_parms * cmd,void * struct_ptr,const char * arg)639 static const char* oidc_set_encrypted_response_alg(cmd_parms *cmd,
640 		void *struct_ptr, const char *arg) {
641 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
642 			&auth_openidc_module);
643 	const char *rv = oidc_valid_encrypted_response_alg(cmd->pool, arg);
644 	if (rv == NULL)
645 		rv = ap_set_string_slot(cmd, cfg, arg);
646 	return OIDC_CONFIG_DIR_RV(cmd, rv);
647 }
648 
649 /*
650  * set the content encryption algorithm to be used by the OP (id_token/user_info)
651  */
oidc_set_encrypted_response_enc(cmd_parms * cmd,void * struct_ptr,const char * arg)652 static const char* oidc_set_encrypted_response_enc(cmd_parms *cmd,
653 		void *struct_ptr, const char *arg) {
654 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
655 			&auth_openidc_module);
656 	const char *rv = oidc_valid_encrypted_response_enc(cmd->pool, arg);
657 	if (rv == NULL)
658 		rv = ap_set_string_slot(cmd, cfg, arg);
659 	return OIDC_CONFIG_DIR_RV(cmd, rv);
660 }
661 
662 /*
663  * set the userinfo endpoint token presentation method
664  */
oidc_set_userinfo_token_method(cmd_parms * cmd,void * struct_ptr,const char * arg)665 static const char* oidc_set_userinfo_token_method(cmd_parms *cmd,
666 		void *struct_ptr, const char *arg) {
667 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
668 			&auth_openidc_module);
669 	const char *rv = oidc_parse_userinfo_token_method(cmd->pool, arg,
670 			&cfg->provider.userinfo_token_method);
671 	return OIDC_CONFIG_DIR_RV(cmd, rv);
672 }
673 
674 /*
675  * set the session inactivity timeout
676  */
oidc_set_session_inactivity_timeout(cmd_parms * cmd,void * struct_ptr,const char * arg)677 static const char* oidc_set_session_inactivity_timeout(cmd_parms *cmd,
678 		void *struct_ptr, const char *arg) {
679 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
680 			&auth_openidc_module);
681 	const char *rv = oidc_parse_session_inactivity_timeout(cmd->pool, arg,
682 			&cfg->session_inactivity_timeout);
683 	return OIDC_CONFIG_DIR_RV(cmd, rv);
684 }
685 
686 /*
687  * set the maximum session duration; 0 means take it from the ID token expiry time
688  */
oidc_set_session_max_duration(cmd_parms * cmd,void * struct_ptr,const char * arg)689 static const char* oidc_set_session_max_duration(cmd_parms *cmd,
690 		void *struct_ptr, const char *arg) {
691 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
692 			&auth_openidc_module);
693 	const char *rv = oidc_parse_session_max_duration(cmd->pool, arg,
694 			&cfg->provider.session_max_duration);
695 	return OIDC_CONFIG_DIR_RV(cmd, rv);
696 }
697 
oidc_cleanup_keys(void * data)698 static apr_status_t oidc_cleanup_keys(void *data) {
699 	apr_array_header_t *keys_list = (apr_array_header_t*) data;
700 	oidc_jwk_t **jwk = NULL;
701 	while ((jwk = apr_array_pop(keys_list))) {
702 		oidc_jwk_destroy(*jwk);
703 	}
704 	return APR_SUCCESS;
705 }
706 
707 /*
708  * add a public key from an X.509 file to our list of JWKs with public keys
709  */
oidc_set_public_key_files(cmd_parms * cmd,void * struct_ptr,const char * arg)710 static const char* oidc_set_public_key_files(cmd_parms *cmd, void *struct_ptr,
711 		const char *arg) {
712 	oidc_jwk_t *jwk = NULL;
713 	oidc_jose_error_t err;
714 
715 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
716 			&auth_openidc_module);
717 
718 	int offset = (int) (long) cmd->info;
719 	apr_array_header_t **public_keys = (apr_array_header_t**) ((char*) cfg
720 			+ offset);
721 
722 	char *kid = NULL, *fname = NULL;
723 	int fname_len;
724 	const char *rv = oidc_parse_enc_kid_key_tuple(cmd->pool, arg, &kid, &fname,
725 			&fname_len, FALSE);
726 	if (rv != NULL)
727 		return rv;
728 
729 	fname = oidc_util_get_full_path(cmd->pool, fname);
730 
731 	if (oidc_jwk_parse_rsa_public_key(cmd->pool, kid, fname, &jwk, &err)
732 			== FALSE) {
733 		return apr_psprintf(cmd->pool,
734 				"oidc_jwk_parse_rsa_public_key failed for (kid=%s) \"%s\": %s",
735 				kid, fname, oidc_jose_e2s(cmd->pool, err));
736 	}
737 
738 	if (*public_keys == NULL) {
739 		*public_keys = apr_array_make(cmd->pool, 4, sizeof(const oidc_jwk_t*));
740 		apr_pool_cleanup_register(cmd->pool, *public_keys, oidc_cleanup_keys,
741 				oidc_cleanup_keys);
742 	}
743 
744 	*(const oidc_jwk_t**) apr_array_push(*public_keys) = jwk;
745 
746 	return NULL;
747 }
748 
749 /*
750  * add a shared key to a list of JWKs with shared keys
751  */
oidc_set_shared_keys(cmd_parms * cmd,void * struct_ptr,const char * arg)752 static const char* oidc_set_shared_keys(cmd_parms *cmd, void *struct_ptr,
753 		const char *arg) {
754 	oidc_jose_error_t err;
755 	oidc_jwk_t *jwk = NULL;
756 
757 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
758 			&auth_openidc_module);
759 	int offset = (int) (long) cmd->info;
760 	apr_hash_t **shared_keys = (apr_hash_t**) ((char*) cfg + offset);
761 
762 	char *kid = NULL, *secret = NULL;
763 	int key_len = 0;
764 	const char *rv = oidc_parse_enc_kid_key_tuple(cmd->pool, arg, &kid, &secret,
765 			&key_len, TRUE);
766 	if (rv != NULL)
767 		return rv;
768 
769 	jwk = oidc_jwk_create_symmetric_key(cmd->pool, kid,
770 			(const unsigned char*) secret, key_len, TRUE, &err);
771 	if (jwk == NULL) {
772 		return apr_psprintf(cmd->pool,
773 				"oidc_jwk_create_symmetric_key failed for (kid=%s) \"%s\": %s",
774 				kid, secret, oidc_jose_e2s(cmd->pool, err));
775 	}
776 
777 	if (*shared_keys == NULL)
778 		*shared_keys = apr_hash_make(cmd->pool);
779 	apr_hash_set(*shared_keys, jwk->kid,
780 			APR_HASH_KEY_STRING, jwk);
781 
782 	return NULL;
783 }
784 
785 /*
786  * add a private key from an RSA private key file to our list of JWKs with private keys
787  */
oidc_set_private_key_files_enc(cmd_parms * cmd,void * dummy,const char * arg)788 static const char* oidc_set_private_key_files_enc(cmd_parms *cmd, void *dummy,
789 		const char *arg) {
790 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
791 			&auth_openidc_module);
792 	oidc_jwk_t *jwk = NULL;
793 	oidc_jose_error_t err;
794 
795 	char *kid = NULL, *fname = NULL;
796 	int fname_len;
797 	const char *rv = oidc_parse_enc_kid_key_tuple(cmd->pool, arg, &kid, &fname,
798 			&fname_len, FALSE);
799 	if (rv != NULL)
800 		return rv;
801 
802 	fname = oidc_util_get_full_path(cmd->pool, fname);
803 
804 	if (oidc_jwk_parse_rsa_private_key(cmd->pool, kid, fname, &jwk, &err)
805 			== FALSE) {
806 		return apr_psprintf(cmd->pool,
807 				"oidc_jwk_parse_rsa_private_key failed for (kid=%s) \"%s\": %s",
808 				kid, fname, oidc_jose_e2s(cmd->pool, err));
809 	}
810 
811 	if (cfg->private_keys == NULL) {
812 		cfg->private_keys = apr_array_make(cmd->pool, 4,
813 				sizeof(const oidc_jwk_t*));
814 		apr_pool_cleanup_register(cmd->pool, cfg->private_keys,
815 				oidc_cleanup_keys, oidc_cleanup_keys);
816 	}
817 
818 	*(const oidc_jwk_t**) apr_array_push(cfg->private_keys) = jwk;
819 
820 	return NULL;
821 }
822 
823 /*
824  * define how to pass the id_token/claims in HTTP headers
825  */
oidc_set_pass_idtoken_as(cmd_parms * cmd,void * dummy,const char * v1,const char * v2,const char * v3)826 static const char* oidc_set_pass_idtoken_as(cmd_parms *cmd, void *dummy,
827 		const char *v1, const char *v2, const char *v3) {
828 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
829 			&auth_openidc_module);
830 	const char *rv = oidc_parse_pass_idtoken_as(cmd->pool, v1, v2, v3,
831 			&cfg->pass_idtoken_as);
832 	return OIDC_CONFIG_DIR_RV(cmd, rv);
833 }
834 
835 /*
836  * define how to pass the userinfo/claims in HTTP headers
837  */
oidc_set_pass_userinfo_as(cmd_parms * cmd,void * dummy,const char * v1,const char * v2,const char * v3)838 static const char* oidc_set_pass_userinfo_as(cmd_parms *cmd, void *dummy,
839 		const char *v1, const char *v2, const char *v3) {
840 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
841 			&auth_openidc_module);
842 	const char *rv = oidc_parse_pass_userinfo_as(cmd->pool, v1, v2, v3,
843 			&cfg->pass_userinfo_as);
844 	return OIDC_CONFIG_DIR_RV(cmd, rv);
845 }
846 
847 /*
848  * define which method of pass an OAuth Bearer token is accepted
849  */
oidc_set_accept_oauth_token_in(cmd_parms * cmd,void * m,const char * arg)850 static const char* oidc_set_accept_oauth_token_in(cmd_parms *cmd, void *m,
851 		const char *arg) {
852 	oidc_dir_cfg *dir_cfg = (oidc_dir_cfg*) m;
853 	const char *rv = oidc_parse_accept_oauth_token_in(cmd->pool, arg,
854 			&dir_cfg->oauth_accept_token_in,
855 			dir_cfg->oauth_accept_token_options);
856 	return OIDC_CONFIG_DIR_RV(cmd, rv);
857 }
858 
859 /*
860  * set the syntax of the token expiry claim in the introspection response
861  */
oidc_set_token_expiry_claim(cmd_parms * cmd,void * dummy,const char * claim_name,const char * claim_format,const char * claim_required)862 static const char* oidc_set_token_expiry_claim(cmd_parms *cmd, void *dummy,
863 		const char *claim_name, const char *claim_format,
864 		const char *claim_required) {
865 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
866 			&auth_openidc_module);
867 
868 	const char *rv = NULL;
869 
870 	cfg->oauth.introspection_token_expiry_claim_name = apr_pstrdup(cmd->pool,
871 			claim_name);
872 
873 	if ((rv == NULL) && (claim_format != NULL)) {
874 		rv = oidc_valid_claim_format(cmd->pool, claim_format);
875 		if (rv == NULL)
876 			cfg->oauth.introspection_token_expiry_claim_format = apr_pstrdup(
877 					cmd->pool, claim_format);
878 	}
879 
880 	if ((rv == NULL) && (claim_required != NULL)) {
881 		rv = oidc_parse_claim_required(cmd->pool, claim_required,
882 				&cfg->oauth.introspection_token_expiry_claim_required);
883 	}
884 
885 	return OIDC_CONFIG_DIR_RV(cmd, rv);
886 }
887 
888 /*
889  * specify cookies names to pass/strip
890  */
oidc_set_cookie_names(cmd_parms * cmd,void * m,const char * arg)891 static const char* oidc_set_cookie_names(cmd_parms *cmd, void *m,
892 		const char *arg) {
893 	oidc_dir_cfg *dir_cfg = (oidc_dir_cfg*) m;
894 	int offset = (int) (long) cmd->info;
895 	apr_array_header_t **cookie_names = (apr_array_header_t**) ((char*) dir_cfg
896 			+ offset);
897 	if (*cookie_names == NULL)
898 		*cookie_names = apr_array_make(cmd->pool, 3, sizeof(const char*));
899 	*(const char**) apr_array_push((*cookie_names)) = arg;
900 	return NULL;
901 }
902 
903 /*
904  * set the HTTP method to use in an OAuth 2.0 token introspection/validation call
905  */
oidc_set_introspection_method(cmd_parms * cmd,void * m,const char * arg)906 static const char* oidc_set_introspection_method(cmd_parms *cmd, void *m,
907 		const char *arg) {
908 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
909 			&auth_openidc_module);
910 	const char *rv = oidc_valid_introspection_method(cmd->pool, arg);
911 	if (rv == NULL)
912 		rv = ap_set_string_slot(cmd, cfg, arg);
913 	return OIDC_CONFIG_DIR_RV(cmd, rv);
914 }
915 
916 /*
917  * set POST preservation behavior
918  */
oidc_set_preserve_post(cmd_parms * cmd,void * m,const char * arg)919 static const char* oidc_set_preserve_post(cmd_parms *cmd, void *m,
920 		const char *arg) {
921 	oidc_dir_cfg *dir_cfg = (oidc_dir_cfg*) m;
922 	int b = 0;
923 	const char *rv = oidc_parse_boolean(cmd->pool, arg, &b);
924 	if (rv == NULL)
925 		rv = ap_set_flag_slot(cmd, dir_cfg, b);
926 	return OIDC_CONFIG_DIR_RV(cmd, rv);
927 }
928 
929 /*
930  * set the remote user name claims, optionally plus the regular expression applied to it
931  */
oidc_set_remote_user_claim(cmd_parms * cmd,void * struct_ptr,const char * v1,const char * v2,const char * v3)932 static const char* oidc_set_remote_user_claim(cmd_parms *cmd, void *struct_ptr,
933 		const char *v1, const char *v2, const char *v3) {
934 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
935 			&auth_openidc_module);
936 
937 	int offset = (int) (long) cmd->info;
938 	oidc_remote_user_claim_t *remote_user_claim =
939 			(oidc_remote_user_claim_t*) ((char*) cfg + offset);
940 
941 	remote_user_claim->claim_name = v1;
942 	if (v2)
943 		remote_user_claim->reg_exp = v2;
944 	if (v3)
945 		remote_user_claim->replace = v3;
946 
947 	return NULL;
948 }
949 
950 /*
951  * define how to pass claims information to the application: in headers and/or environment variables
952  */
oidc_set_pass_claims_as(cmd_parms * cmd,void * m,const char * arg1,const char * arg2)953 static const char* oidc_set_pass_claims_as(cmd_parms *cmd, void *m,
954 		const char *arg1, const char *arg2) {
955 	oidc_dir_cfg *dir_cfg = (oidc_dir_cfg*) m;
956 	const char *rv = oidc_parse_set_claims_as(cmd->pool, arg1,
957 			&dir_cfg->pass_info_in_headers, &dir_cfg->pass_info_in_env_vars);
958 	if (rv == NULL) {
959 		if (arg2 != NULL) {
960 			if (apr_strnatcmp(arg2, "base64url") == 0) {
961 				dir_cfg->pass_info_base64url = 1;
962 			} else {
963 				rv = apr_pstrcat(cmd->temp_pool, "unknown encoding option \"",
964 						arg2, "\", only \"base64url\" is supported", NULL);
965 			}
966 		}
967 	}
968 	return OIDC_CONFIG_DIR_RV(cmd, rv);
969 }
970 
971 /*
972  * define how to act on unauthenticated requests
973  */
oidc_set_unauth_action(cmd_parms * cmd,void * m,const char * arg1,const char * arg2)974 static const char* oidc_set_unauth_action(cmd_parms *cmd, void *m,
975 		const char *arg1, const char *arg2) {
976 	oidc_dir_cfg *dir_cfg = (oidc_dir_cfg*) m;
977 	const char *rv = oidc_parse_unauth_action(cmd->pool, arg1,
978 			&dir_cfg->unauth_action);
979 #if MODULE_MAGIC_NUMBER_MAJOR >= 20100714
980 	const char *expr_err = NULL;
981 	if ((rv == NULL) && (arg2 != NULL)) {
982 		dir_cfg->unauth_expression = ap_expr_parse_cmd(cmd, arg2,
983 				AP_EXPR_FLAG_DONT_VARY & AP_EXPR_FLAG_RESTRICTED, &expr_err,
984 				NULL);
985 		if (expr_err != NULL) {
986 			rv = apr_pstrcat(cmd->temp_pool, "cannot parse expression: ",
987 					expr_err, NULL);
988 		}
989 	}
990 #endif
991 	return OIDC_CONFIG_DIR_RV(cmd, rv);
992 }
993 
994 /*
995  * define how to act on unauthorized requests
996  */
oidc_set_unautz_action(cmd_parms * cmd,void * m,const char * arg)997 static const char* oidc_set_unautz_action(cmd_parms *cmd, void *m,
998 		const char *arg) {
999 	oidc_dir_cfg *dir_cfg = (oidc_dir_cfg*) m;
1000 	const char *rv = oidc_parse_unautz_action(cmd->pool, arg,
1001 			&dir_cfg->unautz_action);
1002 	return OIDC_CONFIG_DIR_RV(cmd, rv);
1003 }
1004 
1005 /*
1006  * set the JWKS refresh interval
1007  */
oidc_set_jwks_refresh_interval(cmd_parms * cmd,void * struct_ptr,const char * arg)1008 static const char* oidc_set_jwks_refresh_interval(cmd_parms *cmd,
1009 		void *struct_ptr, const char *arg) {
1010 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
1011 			&auth_openidc_module);
1012 	const char *rv = oidc_parse_jwks_refresh_interval(cmd->pool, arg,
1013 			&cfg->provider.jwks_refresh_interval);
1014 	return OIDC_CONFIG_DIR_RV(cmd, rv);
1015 }
1016 
1017 /*
1018  * set the ID token "iat" slack
1019  */
oidc_set_idtoken_iat_slack(cmd_parms * cmd,void * struct_ptr,const char * arg)1020 static const char* oidc_set_idtoken_iat_slack(cmd_parms *cmd, void *struct_ptr,
1021 		const char *arg) {
1022 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
1023 			&auth_openidc_module);
1024 	const char *rv = oidc_parse_idtoken_iat_slack(cmd->pool, arg,
1025 			&cfg->provider.idtoken_iat_slack);
1026 	return OIDC_CONFIG_DIR_RV(cmd, rv);
1027 }
1028 
1029 /*
1030  * set the userinfo refresh interval
1031  */
oidc_set_userinfo_refresh_interval(cmd_parms * cmd,void * struct_ptr,const char * arg)1032 static const char* oidc_set_userinfo_refresh_interval(cmd_parms *cmd,
1033 		void *struct_ptr, const char *arg) {
1034 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
1035 			&auth_openidc_module);
1036 	const char *rv = oidc_parse_userinfo_refresh_interval(cmd->pool, arg,
1037 			&cfg->provider.userinfo_refresh_interval);
1038 	return OIDC_CONFIG_DIR_RV(cmd, rv);
1039 }
1040 
1041 /*
1042  * define which data will be returned from the info hook
1043  */
oidc_set_info_hook_data(cmd_parms * cmd,void * m,const char * arg)1044 static const char* oidc_set_info_hook_data(cmd_parms *cmd, void *m,
1045 		const char *arg) {
1046 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
1047 			&auth_openidc_module);
1048 	const char *rv = oidc_parse_info_hook_data(cmd->pool, arg,
1049 			&cfg->info_hook_data);
1050 	return OIDC_CONFIG_DIR_RV(cmd, rv);
1051 }
1052 
oidc_set_filtered_claims(cmd_parms * cmd,void * m,const char * arg)1053 static const char* oidc_set_filtered_claims(cmd_parms *cmd, void *m,
1054 		const char *arg) {
1055 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
1056 			&auth_openidc_module);
1057 	int offset = (int) (long) cmd->info;
1058 	apr_hash_t **list = (apr_hash_t**) ((char*) cfg + offset);
1059 	if (*list == NULL)
1060 		*list = apr_hash_make(cmd->pool);
1061 	apr_hash_set(*list, arg, APR_HASH_KEY_STRING, arg);
1062 	return NULL;
1063 }
1064 
1065 /*
1066  * set the token binding policy
1067  */
oidc_set_token_binding_policy(cmd_parms * cmd,void * struct_ptr,const char * arg)1068 static const char* oidc_set_token_binding_policy(cmd_parms *cmd,
1069 		void *struct_ptr, const char *arg) {
1070 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
1071 			&auth_openidc_module);
1072 	int offset = (int) (long) cmd->info;
1073 	int *token_binding_policy = (int*) ((char*) cfg + offset);
1074 	const char *rv = oidc_parse_token_binding_policy(cmd->pool, arg,
1075 			token_binding_policy);
1076 	return OIDC_CONFIG_DIR_RV(cmd, rv);
1077 }
1078 
1079 /*
1080  * set the claim prefix
1081  */
oidc_cfg_set_claim_prefix(cmd_parms * cmd,void * struct_ptr,const char * args)1082 static const char* oidc_cfg_set_claim_prefix(cmd_parms *cmd, void *struct_ptr,
1083 		const char *args) {
1084 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
1085 			&auth_openidc_module);
1086 	char *w = ap_getword_conf(cmd->pool, &args);
1087 	if (*w == '\0' || *args != 0)
1088 		cfg->claim_prefix = "";
1089 	else
1090 		cfg->claim_prefix = w;
1091 	return NULL;
1092 }
1093 
1094 /*
1095  * get the claim prefix
1096  */
oidc_cfg_claim_prefix(request_rec * r)1097 const char* oidc_cfg_claim_prefix(request_rec *r) {
1098 	oidc_cfg *cfg = ap_get_module_config(r->server->module_config,
1099 			&auth_openidc_module);
1100 	if (cfg->claim_prefix == NULL)
1101 		return OIDC_DEFAULT_CLAIM_PREFIX;
1102 	return cfg->claim_prefix;
1103 }
1104 
1105 /*
1106  * set the HTTP method used to send the authentication request to the provider
1107  */
oidc_set_auth_request_method(cmd_parms * cmd,void * struct_ptr,const char * arg)1108 const char* oidc_set_auth_request_method(cmd_parms *cmd, void *struct_ptr,
1109 		const char *arg) {
1110 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
1111 			&auth_openidc_module);
1112 	const char *rv = oidc_parse_auth_request_method(cmd->pool, arg,
1113 			&cfg->provider.auth_request_method);
1114 	return OIDC_CONFIG_DIR_RV(cmd, rv);
1115 }
1116 
1117 /*
1118  * set the introspection authorization static bearer token
1119  */
oidc_set_client_auth_bearer_token(cmd_parms * cmd,void * struct_ptr,const char * args)1120 static const char* oidc_set_client_auth_bearer_token(cmd_parms *cmd,
1121 		void *struct_ptr, const char *args) {
1122 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
1123 			&auth_openidc_module);
1124 	char *w = ap_getword_conf(cmd->pool, &args);
1125 	cfg->oauth.introspection_client_auth_bearer_token =
1126 			(*w == '\0' || *args != 0) ? "" : w;
1127 	return NULL;
1128 }
1129 
1130 /*
1131  * set the maximum number of parallel state cookies
1132  */
oidc_set_max_number_of_state_cookies(cmd_parms * cmd,void * struct_ptr,const char * arg1,const char * arg2)1133 static const char* oidc_set_max_number_of_state_cookies(cmd_parms *cmd,
1134 		void *struct_ptr, const char *arg1, const char *arg2) {
1135 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
1136 			&auth_openidc_module);
1137 	const char *rv = oidc_parse_max_number_of_state_cookies(cmd->pool, arg1,
1138 			arg2, &cfg->max_number_of_state_cookies,
1139 			&cfg->delete_oldest_state_cookies);
1140 	return OIDC_CONFIG_DIR_RV(cmd, rv);
1141 }
1142 
1143 /*
1144  * return the maximum number of parallel state cookies
1145  */
oidc_cfg_max_number_of_state_cookies(oidc_cfg * cfg)1146 int oidc_cfg_max_number_of_state_cookies(oidc_cfg *cfg) {
1147 	if (cfg->max_number_of_state_cookies == OIDC_CONFIG_POS_INT_UNSET)
1148 		return OIDC_DEFAULT_MAX_NUMBER_OF_STATE_COOKIES;
1149 	return cfg->max_number_of_state_cookies;
1150 }
1151 
1152 /*
1153  * return the number of oldest state cookies that need to be deleted
1154  */
oidc_cfg_delete_oldest_state_cookies(oidc_cfg * cfg)1155 int oidc_cfg_delete_oldest_state_cookies(oidc_cfg *cfg) {
1156 	if (cfg->delete_oldest_state_cookies == OIDC_CONFIG_POS_INT_UNSET)
1157 		return OIDC_DEFAULT_DELETE_OLDEST_STATE_COOKIES;
1158 	return cfg->delete_oldest_state_cookies;
1159 }
1160 
1161 /*
1162  * set the time in seconds that the access token needs to be valid for
1163  */
oidc_set_refresh_access_token_before_expiry(cmd_parms * cmd,void * m,const char * arg1,const char * arg2)1164 static const char* oidc_set_refresh_access_token_before_expiry(cmd_parms *cmd,
1165 		void *m, const char *arg1, const char *arg2) {
1166 	oidc_dir_cfg *dir_cfg = (oidc_dir_cfg*) m;
1167 	const char *rv1 = oidc_parse_refresh_access_token_before_expiry(cmd->pool,
1168 			arg1, &dir_cfg->refresh_access_token_before_expiry);
1169 	if (rv1 != NULL)
1170 		return apr_psprintf(cmd->pool, "Invalid value for directive '%s': %s",
1171 				cmd->directive->directive, rv1);
1172 
1173 	if (arg2) {
1174 		const char *rv2 = oidc_parse_logout_on_error_refresh_as(cmd->pool, arg2,
1175 				&dir_cfg->logout_on_error_refresh);
1176 		return OIDC_CONFIG_DIR_RV(cmd, rv2);
1177 	}
1178 
1179 	return NULL;
1180 }
1181 
1182 /*
1183  * define which header we use for calculating the fingerprint of the state during authentication
1184  */
oidc_set_state_input_headers_as(cmd_parms * cmd,void * m,const char * arg)1185 static const char* oidc_set_state_input_headers_as(cmd_parms *cmd, void *m,
1186 		const char *arg) {
1187 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
1188 			&auth_openidc_module);
1189 	const char *rv = oidc_parse_set_state_input_headers_as(cmd->pool, arg,
1190 			&cfg->state_input_headers);
1191 	return OIDC_CONFIG_DIR_RV(cmd, rv);
1192 }
1193 
oidc_set_redirect_urls_allowed(cmd_parms * cmd,void * m,const char * arg)1194 static const char* oidc_set_redirect_urls_allowed(cmd_parms *cmd, void *m,
1195 		const char *arg) {
1196 	oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config,
1197 			&auth_openidc_module);
1198 	if (cfg->redirect_urls_allowed == NULL)
1199 		cfg->redirect_urls_allowed = apr_hash_make(cmd->pool);
1200 	apr_hash_set(cfg->redirect_urls_allowed, arg, APR_HASH_KEY_STRING, arg);
1201 	return NULL;
1202 }
1203 
oidc_cfg_dir_refresh_access_token_before_expiry(request_rec * r)1204 int oidc_cfg_dir_refresh_access_token_before_expiry(request_rec *r) {
1205 	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
1206 			&auth_openidc_module);
1207 	if (dir_cfg->refresh_access_token_before_expiry == OIDC_CONFIG_POS_INT_UNSET)
1208 		return OIDC_DEFAULT_REFRESH_ACCESS_TOKEN_BEFORE_EXPIRY;
1209 	return dir_cfg->refresh_access_token_before_expiry;
1210 }
1211 
oidc_cfg_dir_logout_on_error_refresh(request_rec * r)1212 int oidc_cfg_dir_logout_on_error_refresh(request_rec *r) {
1213 	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
1214 			&auth_openidc_module);
1215 	if (dir_cfg->logout_on_error_refresh == OIDC_CONFIG_POS_INT_UNSET)
1216 		return 0; // no mask
1217 	return dir_cfg->logout_on_error_refresh;
1218 }
1219 
oidc_cfg_dir_state_cookie_prefix(request_rec * r)1220 char* oidc_cfg_dir_state_cookie_prefix(request_rec *r) {
1221 	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
1222 			&auth_openidc_module);
1223 	if ((dir_cfg->state_cookie_prefix == NULL)
1224 			|| ((dir_cfg->state_cookie_prefix != NULL)
1225 					&& (apr_strnatcmp(dir_cfg->state_cookie_prefix,
1226 							OIDC_CONFIG_STRING_UNSET) == 0)))
1227 		return OIDC_DEFAULT_STATE_COOKIE_PREFIX;
1228 	return dir_cfg->state_cookie_prefix;
1229 }
1230 
oidc_cfg_provider_init(oidc_provider_t * provider)1231 void oidc_cfg_provider_init(oidc_provider_t *provider) {
1232 	provider->metadata_url = NULL;
1233 	provider->issuer = NULL;
1234 	provider->authorization_endpoint_url = NULL;
1235 	provider->token_endpoint_url = NULL;
1236 	provider->token_endpoint_auth = NULL;
1237 	provider->token_endpoint_params = NULL;
1238 	provider->userinfo_endpoint_url = NULL;
1239 	provider->revocation_endpoint_url = NULL;
1240 	provider->client_id = NULL;
1241 	provider->client_secret = NULL;
1242 	provider->token_endpoint_tls_client_cert = NULL;
1243 	provider->token_endpoint_tls_client_key = NULL;
1244 	provider->registration_endpoint_url = NULL;
1245 	provider->registration_endpoint_json = NULL;
1246 	provider->check_session_iframe = NULL;
1247 	provider->end_session_endpoint = NULL;
1248 	provider->jwks_uri = NULL;
1249 	provider->backchannel_logout_supported = OIDC_CONFIG_POS_INT_UNSET;
1250 
1251 	provider->ssl_validate_server = OIDC_DEFAULT_SSL_VALIDATE_SERVER;
1252 	provider->validate_issuer = OIDC_DEFAULT_VALIDATE_ISSUER;
1253 	provider->client_name = OIDC_DEFAULT_CLIENT_NAME;
1254 	provider->client_contact = NULL;
1255 	provider->registration_token = NULL;
1256 	provider->scope = OIDC_DEFAULT_SCOPE;
1257 	provider->response_type = OIDC_DEFAULT_RESPONSE_TYPE;
1258 	provider->response_mode = NULL;
1259 	provider->jwks_refresh_interval = OIDC_DEFAULT_JWKS_REFRESH_INTERVAL;
1260 	provider->idtoken_iat_slack = OIDC_DEFAULT_IDTOKEN_IAT_SLACK;
1261 	provider->session_max_duration = OIDC_DEFAULT_SESSION_MAX_DURATION;
1262 	provider->auth_request_params = NULL;
1263 	provider->pkce = NULL;
1264 
1265 	provider->client_jwks_uri = NULL;
1266 	provider->client_signing_keys = NULL;
1267 	provider->client_encryption_keys = NULL;
1268 
1269 	provider->id_token_signed_response_alg = NULL;
1270 	provider->id_token_encrypted_response_alg = NULL;
1271 	provider->id_token_encrypted_response_enc = NULL;
1272 	provider->userinfo_signed_response_alg = NULL;
1273 	provider->userinfo_encrypted_response_alg = NULL;
1274 	provider->userinfo_encrypted_response_enc = NULL;
1275 	provider->userinfo_token_method = OIDC_USER_INFO_TOKEN_METHOD_HEADER;
1276 	provider->auth_request_method = OIDC_DEFAULT_AUTH_REQUEST_METHOD;
1277 }
1278 
1279 /*
1280  * create a new server config record with defaults
1281  */
oidc_create_server_config(apr_pool_t * pool,server_rec * svr)1282 void* oidc_create_server_config(apr_pool_t *pool, server_rec *svr) {
1283 	oidc_cfg *c = apr_pcalloc(pool, sizeof(oidc_cfg));
1284 
1285 	c->merged = FALSE;
1286 
1287 	c->redirect_uri = NULL;
1288 	c->default_sso_url = NULL;
1289 	c->default_slo_url = NULL;
1290 	c->public_keys = NULL;
1291 	c->private_keys = NULL;
1292 
1293 	oidc_cfg_provider_init(&c->provider);
1294 
1295 	c->oauth.ssl_validate_server = OIDC_DEFAULT_SSL_VALIDATE_SERVER;
1296 	c->oauth.metadata_url = NULL;
1297 	c->oauth.client_id = NULL;
1298 	c->oauth.client_secret = NULL;
1299 	c->oauth.introspection_endpoint_tls_client_cert = NULL;
1300 	c->oauth.introspection_endpoint_tls_client_key = NULL;
1301 	c->oauth.introspection_endpoint_url = NULL;
1302 	c->oauth.introspection_endpoint_method = OIDC_DEFAULT_OAUTH_ENDPOINT_METHOD;
1303 	c->oauth.introspection_endpoint_params = NULL;
1304 	c->oauth.introspection_endpoint_auth = NULL;
1305 	c->oauth.introspection_client_auth_bearer_token = NULL;
1306 	c->oauth.introspection_token_param_name =
1307 			OIDC_DEFAULT_OAUTH_TOKEN_PARAM_NAME;
1308 
1309 	c->oauth.introspection_token_expiry_claim_name =
1310 			OIDC_DEFAULT_OAUTH_EXPIRY_CLAIM_NAME;
1311 	c->oauth.introspection_token_expiry_claim_format =
1312 			OIDC_DEFAULT_OAUTH_EXPIRY_CLAIM_FORMAT;
1313 	c->oauth.introspection_token_expiry_claim_required =
1314 			OIDC_DEFAULT_OAUTH_EXPIRY_CLAIM_REQUIRED;
1315 
1316 	c->oauth.remote_user_claim.claim_name =
1317 			OIDC_DEFAULT_OAUTH_CLAIM_REMOTE_USER;
1318 	c->oauth.remote_user_claim.reg_exp = NULL;
1319 	c->oauth.remote_user_claim.replace = NULL;
1320 
1321 	c->oauth.verify_jwks_uri = NULL;
1322 	c->oauth.verify_public_keys = NULL;
1323 	c->oauth.verify_shared_keys = NULL;
1324 
1325 	c->oauth.access_token_binding_policy =
1326 			OIDC_DEFAULT_OAUTH_ACCESS_TOKEN_BINDING_POLICY;
1327 
1328 	c->cache = &oidc_cache_shm;
1329 	c->cache_cfg = NULL;
1330 	c->cache_encrypt = OIDC_CONFIG_POS_INT_UNSET;
1331 
1332 	c->cache_file_dir = NULL;
1333 	c->cache_file_clean_interval = OIDC_DEFAULT_CACHE_FILE_CLEAN_INTERVAL;
1334 #ifdef USE_MEMCACHE
1335 	c->cache_memcache_servers = NULL;
1336 #endif
1337 	c->cache_shm_size_max = OIDC_DEFAULT_CACHE_SHM_SIZE;
1338 	c->cache_shm_entry_size_max = OIDC_DEFAULT_CACHE_SHM_ENTRY_SIZE_MAX;
1339 #ifdef USE_LIBHIREDIS
1340 	c->cache_redis_server = NULL;
1341 	c->cache_redis_password = NULL;
1342 	c->cache_redis_database = -1;
1343 #endif
1344 
1345 	c->metadata_dir = NULL;
1346 	c->session_type = OIDC_DEFAULT_SESSION_TYPE;
1347 	c->session_cache_fallback_to_cookie = OIDC_CONFIG_POS_INT_UNSET;
1348 	c->persistent_session_cookie = 0;
1349 	c->session_cookie_chunk_size =
1350 			OIDC_DEFAULT_SESSION_CLIENT_COOKIE_CHUNK_SIZE;
1351 
1352 	c->http_timeout_long = OIDC_DEFAULT_HTTP_TIMEOUT_LONG;
1353 	c->http_timeout_short = OIDC_DEFAULT_HTTP_TIMEOUT_SHORT;
1354 	c->state_timeout = OIDC_DEFAULT_STATE_TIMEOUT;
1355 	c->max_number_of_state_cookies = OIDC_CONFIG_POS_INT_UNSET;
1356 	c->delete_oldest_state_cookies = OIDC_CONFIG_POS_INT_UNSET;
1357 	c->session_inactivity_timeout = OIDC_DEFAULT_SESSION_INACTIVITY_TIMEOUT;
1358 
1359 	c->cookie_domain = NULL;
1360 	c->claim_delimiter = OIDC_DEFAULT_CLAIM_DELIMITER;
1361 	c->claim_prefix = NULL;
1362 	c->remote_user_claim.claim_name = OIDC_DEFAULT_CLAIM_REMOTE_USER;
1363 	c->remote_user_claim.reg_exp = NULL;
1364 	c->remote_user_claim.replace = NULL;
1365 	c->pass_idtoken_as = OIDC_PASS_IDTOKEN_AS_CLAIMS;
1366 	c->pass_userinfo_as = OIDC_PASS_USERINFO_AS_CLAIMS;
1367 	c->cookie_http_only = OIDC_DEFAULT_COOKIE_HTTPONLY;
1368 	c->cookie_same_site = OIDC_DEFAULT_COOKIE_SAME_SITE;
1369 
1370 	c->outgoing_proxy = NULL;
1371 	c->crypto_passphrase = NULL;
1372 
1373 	c->error_template = NULL;
1374 
1375 	c->provider.userinfo_refresh_interval =
1376 			OIDC_DEFAULT_USERINFO_REFRESH_INTERVAL;
1377 	c->provider.request_object = NULL;
1378 
1379 	c->provider_metadata_refresh_interval =
1380 			OIDC_DEFAULT_PROVIDER_METADATA_REFRESH_INTERVAL;
1381 
1382 	c->provider.token_binding_policy =
1383 			OIDC_DEFAULT_PROVIDER_TOKEN_BINDING_POLICY;
1384 
1385 	c->info_hook_data = NULL;
1386 	c->black_listed_claims = NULL;
1387 	c->white_listed_claims = NULL;
1388 
1389 	c->provider.issuer_specific_redirect_uri =
1390 			OIDC_DEFAULT_PROVIDER_ISSUER_SPECIFIC_REDIRECT_URI;
1391 
1392 	c->state_input_headers = OIDC_DEFAULT_STATE_INPUT_HEADERS;
1393 
1394 	c->redirect_urls_allowed = NULL;
1395 
1396 	c->ca_bundle_path = NULL;
1397 
1398 	return c;
1399 }
1400 
1401 /*
1402  * merge a new server config with a base one
1403  */
oidc_merge_server_config(apr_pool_t * pool,void * BASE,void * ADD)1404 void* oidc_merge_server_config(apr_pool_t *pool, void *BASE, void *ADD) {
1405 	oidc_cfg *c = apr_pcalloc(pool, sizeof(oidc_cfg));
1406 	oidc_cfg *base = BASE;
1407 	oidc_cfg *add = ADD;
1408 
1409 	c->merged = TRUE;
1410 
1411 	c->redirect_uri =
1412 			add->redirect_uri != NULL ? add->redirect_uri : base->redirect_uri;
1413 	c->default_sso_url =
1414 			add->default_sso_url != NULL ?
1415 					add->default_sso_url : base->default_sso_url;
1416 	c->default_slo_url =
1417 			add->default_slo_url != NULL ?
1418 					add->default_slo_url : base->default_slo_url;
1419 	c->public_keys =
1420 			add->public_keys != NULL ? add->public_keys : base->public_keys;
1421 	c->private_keys =
1422 			add->private_keys != NULL ? add->private_keys : base->private_keys;
1423 
1424 	c->provider.metadata_url =
1425 			add->provider.metadata_url != NULL ?
1426 					add->provider.metadata_url : base->provider.metadata_url;
1427 	c->provider.issuer =
1428 			add->provider.issuer != NULL ?
1429 					add->provider.issuer : base->provider.issuer;
1430 	c->provider.authorization_endpoint_url =
1431 			add->provider.authorization_endpoint_url != NULL ?
1432 					add->provider.authorization_endpoint_url :
1433 					base->provider.authorization_endpoint_url;
1434 	c->provider.token_endpoint_url =
1435 			add->provider.token_endpoint_url != NULL ?
1436 					add->provider.token_endpoint_url :
1437 					base->provider.token_endpoint_url;
1438 	c->provider.token_endpoint_auth =
1439 			add->provider.token_endpoint_auth != NULL ?
1440 					add->provider.token_endpoint_auth :
1441 					base->provider.token_endpoint_auth;
1442 	c->provider.token_endpoint_params =
1443 			add->provider.token_endpoint_params != NULL ?
1444 					add->provider.token_endpoint_params :
1445 					base->provider.token_endpoint_params;
1446 	c->provider.userinfo_endpoint_url =
1447 			add->provider.userinfo_endpoint_url != NULL ?
1448 					add->provider.userinfo_endpoint_url :
1449 					base->provider.userinfo_endpoint_url;
1450 	c->provider.revocation_endpoint_url =
1451 			add->provider.revocation_endpoint_url != NULL ?
1452 					add->provider.revocation_endpoint_url :
1453 					base->provider.revocation_endpoint_url;
1454 	c->provider.jwks_uri =
1455 			add->provider.jwks_uri != NULL ?
1456 					add->provider.jwks_uri : base->provider.jwks_uri;
1457 	c->provider.client_id =
1458 			add->provider.client_id != NULL ?
1459 					add->provider.client_id : base->provider.client_id;
1460 	c->provider.client_secret =
1461 			add->provider.client_secret != NULL ?
1462 					add->provider.client_secret : base->provider.client_secret;
1463 
1464 	c->provider.token_endpoint_tls_client_key =
1465 			add->provider.token_endpoint_tls_client_key != NULL ?
1466 					add->provider.token_endpoint_tls_client_key :
1467 					base->provider.token_endpoint_tls_client_key;
1468 	c->provider.token_endpoint_tls_client_cert =
1469 			add->provider.token_endpoint_tls_client_cert != NULL ?
1470 					add->provider.token_endpoint_tls_client_cert :
1471 					base->provider.token_endpoint_tls_client_cert;
1472 
1473 	c->provider.registration_endpoint_url =
1474 			add->provider.registration_endpoint_url != NULL ?
1475 					add->provider.registration_endpoint_url :
1476 					base->provider.registration_endpoint_url;
1477 	c->provider.registration_endpoint_json =
1478 			add->provider.registration_endpoint_json != NULL ?
1479 					add->provider.registration_endpoint_json :
1480 					base->provider.registration_endpoint_json;
1481 
1482 	c->provider.check_session_iframe =
1483 			add->provider.check_session_iframe != NULL ?
1484 					add->provider.check_session_iframe :
1485 					base->provider.check_session_iframe;
1486 	c->provider.end_session_endpoint =
1487 			add->provider.end_session_endpoint != NULL ?
1488 					add->provider.end_session_endpoint :
1489 					base->provider.end_session_endpoint;
1490 	c->provider.backchannel_logout_supported =
1491 			add->provider.backchannel_logout_supported
1492 			!= OIDC_CONFIG_POS_INT_UNSET ?
1493 					add->provider.backchannel_logout_supported :
1494 					base->provider.backchannel_logout_supported;
1495 
1496 	c->provider.ssl_validate_server =
1497 			add->provider.ssl_validate_server
1498 			!= OIDC_DEFAULT_SSL_VALIDATE_SERVER ?
1499 					add->provider.ssl_validate_server :
1500 					base->provider.ssl_validate_server;
1501 	c->provider.validate_issuer =
1502 			add->provider.validate_issuer != OIDC_DEFAULT_VALIDATE_ISSUER ?
1503 					add->provider.validate_issuer :
1504 					base->provider.validate_issuer;
1505 	c->provider.client_name =
1506 			apr_strnatcmp(add->provider.client_name, OIDC_DEFAULT_CLIENT_NAME)
1507 			!= 0 ?
1508 					add->provider.client_name : base->provider.client_name;
1509 	c->provider.client_contact =
1510 			add->provider.client_contact != NULL ?
1511 					add->provider.client_contact :
1512 					base->provider.client_contact;
1513 	c->provider.registration_token =
1514 			add->provider.registration_token != NULL ?
1515 					add->provider.registration_token :
1516 					base->provider.registration_token;
1517 	c->provider.scope =
1518 			apr_strnatcmp(add->provider.scope, OIDC_DEFAULT_SCOPE) != 0 ?
1519 					add->provider.scope : base->provider.scope;
1520 	c->provider.response_type =
1521 			apr_strnatcmp(add->provider.response_type,
1522 					OIDC_DEFAULT_RESPONSE_TYPE) != 0 ?
1523 							add->provider.response_type : base->provider.response_type;
1524 	c->provider.response_mode =
1525 			add->provider.response_mode != NULL ?
1526 					add->provider.response_mode : base->provider.response_mode;
1527 	c->provider.jwks_refresh_interval =
1528 			add->provider.jwks_refresh_interval
1529 			!= OIDC_DEFAULT_JWKS_REFRESH_INTERVAL ?
1530 					add->provider.jwks_refresh_interval :
1531 					base->provider.jwks_refresh_interval;
1532 	c->provider.idtoken_iat_slack =
1533 			add->provider.idtoken_iat_slack != OIDC_DEFAULT_IDTOKEN_IAT_SLACK ?
1534 					add->provider.idtoken_iat_slack :
1535 					base->provider.idtoken_iat_slack;
1536 	c->provider.session_max_duration =
1537 			add->provider.session_max_duration
1538 			!= OIDC_DEFAULT_SESSION_MAX_DURATION ?
1539 					add->provider.session_max_duration :
1540 					base->provider.session_max_duration;
1541 	c->provider.auth_request_params =
1542 			add->provider.auth_request_params != NULL ?
1543 					add->provider.auth_request_params :
1544 					base->provider.auth_request_params;
1545 	c->provider.pkce =
1546 			add->provider.pkce != NULL ?
1547 					add->provider.pkce : base->provider.pkce;
1548 
1549 	c->provider.client_jwks_uri =
1550 			add->provider.client_jwks_uri != NULL ?
1551 					add->provider.client_jwks_uri :
1552 					base->provider.client_jwks_uri;
1553 	c->provider.client_signing_keys =
1554 			add->provider.client_signing_keys != NULL ?
1555 					add->provider.client_signing_keys :
1556 					base->provider.client_signing_keys;
1557 	c->provider.client_encryption_keys =
1558 			add->provider.client_encryption_keys != NULL ?
1559 					add->provider.client_encryption_keys :
1560 					base->provider.client_encryption_keys;
1561 
1562 	c->provider.id_token_signed_response_alg =
1563 			add->provider.id_token_signed_response_alg != NULL ?
1564 					add->provider.id_token_signed_response_alg :
1565 					base->provider.id_token_signed_response_alg;
1566 	c->provider.id_token_encrypted_response_alg =
1567 			add->provider.id_token_encrypted_response_alg != NULL ?
1568 					add->provider.id_token_encrypted_response_alg :
1569 					base->provider.id_token_encrypted_response_alg;
1570 	c->provider.id_token_encrypted_response_enc =
1571 			add->provider.id_token_encrypted_response_enc != NULL ?
1572 					add->provider.id_token_encrypted_response_enc :
1573 					base->provider.id_token_encrypted_response_enc;
1574 	c->provider.userinfo_signed_response_alg =
1575 			add->provider.userinfo_signed_response_alg != NULL ?
1576 					add->provider.userinfo_signed_response_alg :
1577 					base->provider.userinfo_signed_response_alg;
1578 	c->provider.userinfo_encrypted_response_alg =
1579 			add->provider.userinfo_encrypted_response_alg != NULL ?
1580 					add->provider.userinfo_encrypted_response_alg :
1581 					base->provider.userinfo_encrypted_response_alg;
1582 	c->provider.userinfo_encrypted_response_enc =
1583 			add->provider.userinfo_encrypted_response_enc != NULL ?
1584 					add->provider.userinfo_encrypted_response_enc :
1585 					base->provider.userinfo_encrypted_response_enc;
1586 	c->provider.userinfo_token_method =
1587 			add->provider.userinfo_token_method
1588 			!= OIDC_USER_INFO_TOKEN_METHOD_HEADER ?
1589 					add->provider.userinfo_token_method :
1590 					base->provider.userinfo_token_method;
1591 	c->provider.auth_request_method =
1592 			add->provider.auth_request_method
1593 			!= OIDC_DEFAULT_AUTH_REQUEST_METHOD ?
1594 					add->provider.auth_request_method :
1595 					base->provider.auth_request_method;
1596 
1597 	c->oauth.ssl_validate_server =
1598 			add->oauth.ssl_validate_server != OIDC_DEFAULT_SSL_VALIDATE_SERVER ?
1599 					add->oauth.ssl_validate_server :
1600 					base->oauth.ssl_validate_server;
1601 	c->oauth.metadata_url =
1602 			add->oauth.metadata_url != NULL ?
1603 					add->oauth.metadata_url : base->oauth.metadata_url;
1604 	c->oauth.client_id =
1605 			add->oauth.client_id != NULL ?
1606 					add->oauth.client_id : base->oauth.client_id;
1607 	c->oauth.client_secret =
1608 			add->oauth.client_secret != NULL ?
1609 					add->oauth.client_secret : base->oauth.client_secret;
1610 
1611 	c->oauth.introspection_endpoint_tls_client_key =
1612 			add->oauth.introspection_endpoint_tls_client_key != NULL ?
1613 					add->oauth.introspection_endpoint_tls_client_key :
1614 					base->oauth.introspection_endpoint_tls_client_key;
1615 	c->oauth.introspection_endpoint_tls_client_cert =
1616 			add->oauth.introspection_endpoint_tls_client_cert != NULL ?
1617 					add->oauth.introspection_endpoint_tls_client_cert :
1618 					base->oauth.introspection_endpoint_tls_client_cert;
1619 
1620 	c->oauth.introspection_endpoint_url =
1621 			add->oauth.introspection_endpoint_url != NULL ?
1622 					add->oauth.introspection_endpoint_url :
1623 					base->oauth.introspection_endpoint_url;
1624 	c->oauth.introspection_endpoint_method =
1625 			apr_strnatcmp(add->oauth.introspection_endpoint_method,
1626 					OIDC_DEFAULT_OAUTH_ENDPOINT_METHOD) != 0 ?
1627 							add->oauth.introspection_endpoint_method :
1628 							base->oauth.introspection_endpoint_method;
1629 	c->oauth.introspection_endpoint_params =
1630 			add->oauth.introspection_endpoint_params != NULL ?
1631 					add->oauth.introspection_endpoint_params :
1632 					base->oauth.introspection_endpoint_params;
1633 	c->oauth.introspection_endpoint_auth =
1634 			add->oauth.introspection_endpoint_auth != NULL ?
1635 					add->oauth.introspection_endpoint_auth :
1636 					base->oauth.introspection_endpoint_auth;
1637 	c->oauth.introspection_client_auth_bearer_token =
1638 			add->oauth.introspection_client_auth_bearer_token != NULL ?
1639 					add->oauth.introspection_client_auth_bearer_token :
1640 					base->oauth.introspection_client_auth_bearer_token;
1641 	c->oauth.introspection_token_param_name =
1642 			apr_strnatcmp(add->oauth.introspection_token_param_name,
1643 					OIDC_DEFAULT_OAUTH_TOKEN_PARAM_NAME) != 0 ?
1644 							add->oauth.introspection_token_param_name :
1645 							base->oauth.introspection_token_param_name;
1646 
1647 	c->oauth.introspection_token_expiry_claim_name =
1648 			apr_strnatcmp(add->oauth.introspection_token_expiry_claim_name,
1649 					OIDC_DEFAULT_OAUTH_EXPIRY_CLAIM_NAME) != 0 ?
1650 							add->oauth.introspection_token_expiry_claim_name :
1651 							base->oauth.introspection_token_expiry_claim_name;
1652 	c->oauth.introspection_token_expiry_claim_format =
1653 			apr_strnatcmp(add->oauth.introspection_token_expiry_claim_format,
1654 					OIDC_DEFAULT_OAUTH_EXPIRY_CLAIM_FORMAT) != 0 ?
1655 							add->oauth.introspection_token_expiry_claim_format :
1656 							base->oauth.introspection_token_expiry_claim_format;
1657 	c->oauth.introspection_token_expiry_claim_required =
1658 			add->oauth.introspection_token_expiry_claim_required
1659 			!= OIDC_DEFAULT_OAUTH_EXPIRY_CLAIM_REQUIRED ?
1660 					add->oauth.introspection_token_expiry_claim_required :
1661 					base->oauth.introspection_token_expiry_claim_required;
1662 
1663 	c->oauth.remote_user_claim.claim_name =
1664 			apr_strnatcmp(add->oauth.remote_user_claim.claim_name,
1665 					OIDC_DEFAULT_OAUTH_CLAIM_REMOTE_USER) != 0 ?
1666 							add->oauth.remote_user_claim.claim_name :
1667 							base->oauth.remote_user_claim.claim_name;
1668 	c->oauth.remote_user_claim.reg_exp =
1669 			add->oauth.remote_user_claim.reg_exp != NULL ?
1670 					add->oauth.remote_user_claim.reg_exp :
1671 					base->oauth.remote_user_claim.reg_exp;
1672 	c->oauth.remote_user_claim.replace =
1673 			add->oauth.remote_user_claim.replace != NULL ?
1674 					add->oauth.remote_user_claim.replace :
1675 					base->oauth.remote_user_claim.replace;
1676 
1677 	c->oauth.verify_jwks_uri =
1678 			add->oauth.verify_jwks_uri != NULL ?
1679 					add->oauth.verify_jwks_uri : base->oauth.verify_jwks_uri;
1680 	c->oauth.verify_public_keys =
1681 			add->oauth.verify_public_keys != NULL ?
1682 					add->oauth.verify_public_keys :
1683 					base->oauth.verify_public_keys;
1684 	c->oauth.verify_shared_keys =
1685 			add->oauth.verify_shared_keys != NULL ?
1686 					add->oauth.verify_shared_keys :
1687 					base->oauth.verify_shared_keys;
1688 
1689 	c->oauth.access_token_binding_policy =
1690 			add->oauth.access_token_binding_policy
1691 			!= OIDC_DEFAULT_OAUTH_ACCESS_TOKEN_BINDING_POLICY ?
1692 					add->oauth.access_token_binding_policy :
1693 					base->oauth.access_token_binding_policy;
1694 
1695 	c->http_timeout_long =
1696 			add->http_timeout_long != OIDC_DEFAULT_HTTP_TIMEOUT_LONG ?
1697 					add->http_timeout_long : base->http_timeout_long;
1698 	c->http_timeout_short =
1699 			add->http_timeout_short != OIDC_DEFAULT_HTTP_TIMEOUT_SHORT ?
1700 					add->http_timeout_short : base->http_timeout_short;
1701 	c->state_timeout =
1702 			add->state_timeout != OIDC_DEFAULT_STATE_TIMEOUT ?
1703 					add->state_timeout : base->state_timeout;
1704 	c->max_number_of_state_cookies =
1705 			add->max_number_of_state_cookies != OIDC_CONFIG_POS_INT_UNSET ?
1706 					add->max_number_of_state_cookies :
1707 					base->max_number_of_state_cookies;
1708 	c->delete_oldest_state_cookies =
1709 			add->delete_oldest_state_cookies != OIDC_CONFIG_POS_INT_UNSET ?
1710 					add->delete_oldest_state_cookies :
1711 					base->delete_oldest_state_cookies;
1712 	c->session_inactivity_timeout =
1713 			add->session_inactivity_timeout
1714 			!= OIDC_DEFAULT_SESSION_INACTIVITY_TIMEOUT ?
1715 					add->session_inactivity_timeout :
1716 					base->session_inactivity_timeout;
1717 
1718 	if (add->cache != &oidc_cache_shm) {
1719 		c->cache = add->cache;
1720 	} else {
1721 		c->cache = base->cache;
1722 	}
1723 
1724 	c->cache_encrypt =
1725 			add->cache_encrypt != OIDC_CONFIG_POS_INT_UNSET ?
1726 					add->cache_encrypt : base->cache_encrypt;
1727 
1728 	c->cache_cfg = NULL;
1729 
1730 	c->cache_file_dir =
1731 			add->cache_file_dir != NULL ?
1732 					add->cache_file_dir : base->cache_file_dir;
1733 	c->cache_file_clean_interval =
1734 			add->cache_file_clean_interval
1735 			!= OIDC_DEFAULT_CACHE_FILE_CLEAN_INTERVAL ?
1736 					add->cache_file_clean_interval :
1737 					base->cache_file_clean_interval;
1738 
1739 #ifdef USE_MEMCACHE
1740 	c->cache_memcache_servers =
1741 			add->cache_memcache_servers != NULL ?
1742 					add->cache_memcache_servers : base->cache_memcache_servers;
1743 #endif
1744 	c->cache_shm_size_max =
1745 			add->cache_shm_size_max != OIDC_DEFAULT_CACHE_SHM_SIZE ?
1746 					add->cache_shm_size_max : base->cache_shm_size_max;
1747 	c->cache_shm_entry_size_max =
1748 			add->cache_shm_entry_size_max
1749 			!= OIDC_DEFAULT_CACHE_SHM_ENTRY_SIZE_MAX ?
1750 					add->cache_shm_entry_size_max :
1751 					base->cache_shm_entry_size_max;
1752 
1753 #ifdef USE_LIBHIREDIS
1754 	c->cache_redis_server =
1755 			add->cache_redis_server != NULL ?
1756 					add->cache_redis_server : base->cache_redis_server;
1757 	c->cache_redis_password =
1758 			add->cache_redis_password != NULL ?
1759 					add->cache_redis_password : base->cache_redis_password;
1760 	c->cache_redis_database =
1761 			add->cache_redis_database != -1 ?
1762 					add->cache_redis_database : base->cache_redis_database;
1763 #endif
1764 
1765 	c->metadata_dir =
1766 			add->metadata_dir != NULL ? add->metadata_dir : base->metadata_dir;
1767 	c->session_type =
1768 			add->session_type != OIDC_DEFAULT_SESSION_TYPE ?
1769 					add->session_type : base->session_type;
1770 	c->session_cache_fallback_to_cookie =
1771 			add->session_cache_fallback_to_cookie != OIDC_CONFIG_POS_INT_UNSET ?
1772 					add->session_cache_fallback_to_cookie :
1773 					base->session_cache_fallback_to_cookie;
1774 	c->persistent_session_cookie =
1775 			add->persistent_session_cookie != 0 ?
1776 					add->persistent_session_cookie :
1777 					base->persistent_session_cookie;
1778 	c->session_cookie_chunk_size =
1779 			add->session_cookie_chunk_size
1780 			!= OIDC_DEFAULT_SESSION_CLIENT_COOKIE_CHUNK_SIZE ?
1781 					add->session_cookie_chunk_size :
1782 					base->session_cookie_chunk_size;
1783 
1784 	c->cookie_domain =
1785 			add->cookie_domain != NULL ?
1786 					add->cookie_domain : base->cookie_domain;
1787 	c->claim_delimiter =
1788 			apr_strnatcmp(add->claim_delimiter, OIDC_DEFAULT_CLAIM_DELIMITER)
1789 			!= 0 ? add->claim_delimiter : base->claim_delimiter;
1790 	c->claim_prefix =
1791 			add->claim_prefix != NULL ? add->claim_prefix : base->claim_prefix;
1792 	c->remote_user_claim.claim_name =
1793 			apr_strnatcmp(add->remote_user_claim.claim_name,
1794 					OIDC_DEFAULT_CLAIM_REMOTE_USER) != 0 ?
1795 							add->remote_user_claim.claim_name :
1796 							base->remote_user_claim.claim_name;
1797 	c->remote_user_claim.reg_exp =
1798 			add->remote_user_claim.reg_exp != NULL ?
1799 					add->remote_user_claim.reg_exp :
1800 					base->remote_user_claim.reg_exp;
1801 	c->remote_user_claim.replace =
1802 			add->remote_user_claim.replace != NULL ?
1803 					add->remote_user_claim.replace :
1804 					base->remote_user_claim.replace;
1805 	c->pass_idtoken_as =
1806 			add->pass_idtoken_as != OIDC_PASS_IDTOKEN_AS_CLAIMS ?
1807 					add->pass_idtoken_as : base->pass_idtoken_as;
1808 	c->pass_userinfo_as =
1809 			add->pass_userinfo_as != OIDC_PASS_USERINFO_AS_CLAIMS ?
1810 					add->pass_userinfo_as : base->pass_userinfo_as;
1811 	c->cookie_http_only =
1812 			add->cookie_http_only != OIDC_DEFAULT_COOKIE_HTTPONLY ?
1813 					add->cookie_http_only : base->cookie_http_only;
1814 	c->cookie_same_site =
1815 			add->cookie_same_site != OIDC_DEFAULT_COOKIE_SAME_SITE ?
1816 					add->cookie_same_site : base->cookie_same_site;
1817 
1818 	c->outgoing_proxy =
1819 			add->outgoing_proxy != NULL ?
1820 					add->outgoing_proxy : base->outgoing_proxy;
1821 
1822 	c->crypto_passphrase =
1823 			add->crypto_passphrase != NULL ?
1824 					add->crypto_passphrase : base->crypto_passphrase;
1825 
1826 	c->error_template =
1827 			add->error_template != NULL ?
1828 					add->error_template : base->error_template;
1829 
1830 	c->provider.userinfo_refresh_interval =
1831 			add->provider.userinfo_refresh_interval
1832 			!= OIDC_DEFAULT_USERINFO_REFRESH_INTERVAL ?
1833 					add->provider.userinfo_refresh_interval :
1834 					base->provider.userinfo_refresh_interval;
1835 	c->provider.request_object =
1836 			add->provider.request_object != NULL ?
1837 					add->provider.request_object :
1838 					base->provider.request_object;
1839 
1840 	c->provider_metadata_refresh_interval =
1841 			add->provider_metadata_refresh_interval
1842 			!= OIDC_DEFAULT_PROVIDER_METADATA_REFRESH_INTERVAL ?
1843 					add->provider_metadata_refresh_interval :
1844 					base->provider_metadata_refresh_interval;
1845 
1846 	c->provider.token_binding_policy =
1847 			add->provider.token_binding_policy
1848 			!= OIDC_DEFAULT_PROVIDER_TOKEN_BINDING_POLICY ?
1849 					add->provider.token_binding_policy :
1850 					base->provider.token_binding_policy;
1851 
1852 	c->info_hook_data =
1853 			add->info_hook_data != NULL ?
1854 					add->info_hook_data : base->info_hook_data;
1855 	c->black_listed_claims =
1856 			add->black_listed_claims != NULL ?
1857 					add->black_listed_claims : base->black_listed_claims;
1858 	c->white_listed_claims =
1859 			add->white_listed_claims != NULL ?
1860 					add->white_listed_claims : base->white_listed_claims;
1861 
1862 	c->provider.issuer_specific_redirect_uri =
1863 			add->provider.issuer_specific_redirect_uri
1864 			!= OIDC_DEFAULT_PROVIDER_ISSUER_SPECIFIC_REDIRECT_URI ?
1865 					add->provider.issuer_specific_redirect_uri :
1866 					base->provider.issuer_specific_redirect_uri;
1867 
1868 	c->state_input_headers =
1869 			add->state_input_headers != OIDC_DEFAULT_STATE_INPUT_HEADERS ?
1870 					add->state_input_headers : base->state_input_headers;
1871 
1872 	c->redirect_urls_allowed =
1873 			add->redirect_urls_allowed != NULL ?
1874 					add->redirect_urls_allowed : base->redirect_urls_allowed;
1875 
1876 	c->ca_bundle_path =
1877 			add->ca_bundle_path != NULL ?
1878 					add->ca_bundle_path : base->ca_bundle_path;
1879 
1880 	return c;
1881 }
1882 
oidc_cfg_cache_encrypt(request_rec * r)1883 int oidc_cfg_cache_encrypt(request_rec *r) {
1884 	oidc_cfg *cfg = ap_get_module_config(r->server->module_config,
1885 			&auth_openidc_module);
1886 	if (cfg->cache_encrypt == OIDC_CONFIG_POS_INT_UNSET)
1887 		return cfg->cache->encrypt_by_default;
1888 	return cfg->cache_encrypt;
1889 }
1890 
oidc_cfg_session_cache_fallback_to_cookie(request_rec * r)1891 int oidc_cfg_session_cache_fallback_to_cookie(request_rec *r) {
1892 	oidc_cfg *cfg = ap_get_module_config(r->server->module_config,
1893 			&auth_openidc_module);
1894 	if (cfg->session_cache_fallback_to_cookie == OIDC_CONFIG_POS_INT_UNSET)
1895 		return 0;
1896 	return cfg->session_cache_fallback_to_cookie;
1897 }
1898 
1899 /*
1900  * create a new directory config record with defaults
1901  */
oidc_create_dir_config(apr_pool_t * pool,char * path)1902 void* oidc_create_dir_config(apr_pool_t *pool, char *path) {
1903 	oidc_dir_cfg *c = apr_pcalloc(pool, sizeof(oidc_dir_cfg));
1904 	c->discover_url = OIDC_CONFIG_STRING_UNSET;
1905 	c->cookie = OIDC_CONFIG_STRING_UNSET;
1906 	c->cookie_path = OIDC_CONFIG_STRING_UNSET;
1907 	c->authn_header = OIDC_CONFIG_STRING_UNSET;
1908 	c->unauth_action = OIDC_CONFIG_POS_INT_UNSET;
1909 #if MODULE_MAGIC_NUMBER_MAJOR >= 20100714
1910 	c->unauth_expression = NULL;
1911 #endif
1912 	c->unautz_action = OIDC_CONFIG_POS_INT_UNSET;
1913 	c->pass_cookies = NULL;
1914 	c->strip_cookies = NULL;
1915 	c->pass_info_in_headers = OIDC_CONFIG_POS_INT_UNSET;
1916 	c->pass_info_in_env_vars = OIDC_CONFIG_POS_INT_UNSET;
1917 	c->pass_info_base64url = OIDC_CONFIG_POS_INT_UNSET;
1918 	c->oauth_accept_token_in = OIDC_CONFIG_POS_INT_UNSET;
1919 	c->oauth_accept_token_options = apr_hash_make(pool);
1920 	c->oauth_token_introspect_interval = -2;
1921 	c->preserve_post = OIDC_CONFIG_POS_INT_UNSET;
1922 	c->pass_refresh_token = OIDC_CONFIG_POS_INT_UNSET;
1923 	c->path_auth_request_params = NULL;
1924 	c->path_scope = NULL;
1925 	c->refresh_access_token_before_expiry = OIDC_CONFIG_POS_INT_UNSET;
1926 	c->logout_on_error_refresh = OIDC_CONFIG_POS_INT_UNSET;
1927 	c->state_cookie_prefix = OIDC_CONFIG_STRING_UNSET;
1928 	return (c);
1929 }
1930 
oidc_cfg_dir_discover_url(request_rec * r)1931 char* oidc_cfg_dir_discover_url(request_rec *r) {
1932 	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
1933 			&auth_openidc_module);
1934 	if ((dir_cfg->discover_url != NULL) && (apr_strnatcmp(dir_cfg->discover_url,
1935 			OIDC_CONFIG_STRING_UNSET) == 0))
1936 		return NULL;
1937 	return dir_cfg->discover_url;
1938 }
1939 
oidc_cfg_dir_cookie(request_rec * r)1940 char* oidc_cfg_dir_cookie(request_rec *r) {
1941 	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
1942 			&auth_openidc_module);
1943 	if ((dir_cfg->cookie == NULL)
1944 			|| ((dir_cfg->cookie != NULL)
1945 					&& (apr_strnatcmp(dir_cfg->cookie, OIDC_CONFIG_STRING_UNSET)
1946 							== 0)))
1947 		return OIDC_DEFAULT_COOKIE;
1948 	return dir_cfg->cookie;
1949 }
1950 
oidc_cfg_dir_cookie_path(request_rec * r)1951 char* oidc_cfg_dir_cookie_path(request_rec *r) {
1952 	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
1953 			&auth_openidc_module);
1954 	if ((dir_cfg->cookie_path == NULL)
1955 			|| ((dir_cfg->cookie_path != NULL)
1956 					&& (apr_strnatcmp(dir_cfg->cookie_path,
1957 							OIDC_CONFIG_STRING_UNSET) == 0)))
1958 		return OIDC_DEFAULT_COOKIE_PATH;
1959 	return dir_cfg->cookie_path;
1960 }
1961 
oidc_cfg_dir_authn_header(request_rec * r)1962 char* oidc_cfg_dir_authn_header(request_rec *r) {
1963 	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
1964 			&auth_openidc_module);
1965 	if ((dir_cfg->authn_header == NULL)
1966 			|| ((dir_cfg->authn_header != NULL)
1967 					&& (apr_strnatcmp(dir_cfg->authn_header,
1968 							OIDC_CONFIG_STRING_UNSET) == 0)))
1969 		return OIDC_DEFAULT_AUTHN_HEADER;
1970 	return dir_cfg->authn_header;
1971 }
1972 
oidc_cfg_dir_pass_info_in_headers(request_rec * r)1973 apr_byte_t oidc_cfg_dir_pass_info_in_headers(request_rec *r) {
1974 	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
1975 			&auth_openidc_module);
1976 	if (dir_cfg->pass_info_in_headers == OIDC_CONFIG_POS_INT_UNSET)
1977 		return OIDC_DEFAULT_PASS_APP_INFO_IN_HEADERS;
1978 	return dir_cfg->pass_info_in_headers;
1979 }
1980 
oidc_cfg_dir_pass_info_in_envvars(request_rec * r)1981 apr_byte_t oidc_cfg_dir_pass_info_in_envvars(request_rec *r) {
1982 	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
1983 			&auth_openidc_module);
1984 	if (dir_cfg->pass_info_in_env_vars == OIDC_CONFIG_POS_INT_UNSET)
1985 		return OIDC_DEFAULT_PASS_APP_INFO_IN_ENVVARS;
1986 	return dir_cfg->pass_info_in_env_vars;
1987 }
1988 
oidc_cfg_dir_pass_info_base64url(request_rec * r)1989 apr_byte_t oidc_cfg_dir_pass_info_base64url(request_rec *r) {
1990 	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
1991 			&auth_openidc_module);
1992 	if (dir_cfg->pass_info_base64url == OIDC_CONFIG_POS_INT_UNSET)
1993 		return OIDC_DEFAULT_PASS_APP_INFO_BASE64URL;
1994 	return dir_cfg->pass_info_base64url;
1995 }
1996 
oidc_cfg_dir_pass_refresh_token(request_rec * r)1997 apr_byte_t oidc_cfg_dir_pass_refresh_token(request_rec *r) {
1998 	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
1999 			&auth_openidc_module);
2000 	if (dir_cfg->pass_refresh_token == OIDC_CONFIG_POS_INT_UNSET)
2001 		return OIDC_DEFAULT_PASS_REFRESH_TOKEN;
2002 	return dir_cfg->pass_refresh_token;
2003 }
2004 
oidc_cfg_dir_accept_token_in(request_rec * r)2005 apr_byte_t oidc_cfg_dir_accept_token_in(request_rec *r) {
2006 	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
2007 			&auth_openidc_module);
2008 	if (dir_cfg->oauth_accept_token_in == OIDC_CONFIG_POS_INT_UNSET)
2009 		return OIDC_OAUTH_ACCEPT_TOKEN_IN_DEFAULT;
2010 	return dir_cfg->oauth_accept_token_in;
2011 }
2012 
oidc_cfg_dir_accept_token_in_option(request_rec * r,const char * key)2013 char* oidc_cfg_dir_accept_token_in_option(request_rec *r, const char *key) {
2014 	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
2015 			&auth_openidc_module);
2016 	return apr_hash_get(dir_cfg->oauth_accept_token_options, key,
2017 			APR_HASH_KEY_STRING);
2018 }
2019 
oidc_cfg_token_introspection_interval(request_rec * r)2020 int oidc_cfg_token_introspection_interval(request_rec *r) {
2021 	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
2022 			&auth_openidc_module);
2023 	if (dir_cfg->oauth_token_introspect_interval <= -2)
2024 		return OIDC_DEFAULT_TOKEN_INTROSPECTION_INTERVAL;
2025 	return dir_cfg->oauth_token_introspect_interval;
2026 }
2027 
oidc_cfg_dir_preserve_post(request_rec * r)2028 int oidc_cfg_dir_preserve_post(request_rec *r) {
2029 	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
2030 			&auth_openidc_module);
2031 	if (dir_cfg->preserve_post == OIDC_CONFIG_POS_INT_UNSET)
2032 		return OIDC_DEFAULT_PRESERVE_POST;
2033 	return dir_cfg->preserve_post;
2034 }
2035 
oidc_dir_cfg_pass_cookies(request_rec * r)2036 apr_array_header_t* oidc_dir_cfg_pass_cookies(request_rec *r) {
2037 	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
2038 			&auth_openidc_module);
2039 	return dir_cfg->pass_cookies;
2040 }
2041 
oidc_dir_cfg_strip_cookies(request_rec * r)2042 apr_array_header_t* oidc_dir_cfg_strip_cookies(request_rec *r) {
2043 	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
2044 			&auth_openidc_module);
2045 	return dir_cfg->strip_cookies;
2046 }
2047 
oidc_dir_cfg_unauth_action(request_rec * r)2048 int oidc_dir_cfg_unauth_action(request_rec *r) {
2049 	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
2050 			&auth_openidc_module);
2051 
2052 	if (dir_cfg->unauth_action == OIDC_CONFIG_POS_INT_UNSET)
2053 		return OIDC_DEFAULT_UNAUTH_ACTION;
2054 
2055 #if MODULE_MAGIC_NUMBER_MAJOR >= 20100714
2056 	int rc = 0;
2057 	const char *err_str = NULL;
2058 	if (dir_cfg->unauth_expression == NULL)
2059 		return dir_cfg->unauth_action;
2060 
2061 	rc = ap_expr_exec(r, dir_cfg->unauth_expression, &err_str);
2062 
2063 	if (rc < 0) {
2064 		oidc_warn(r, "executing expression failed");
2065 		return OIDC_DEFAULT_UNAUTH_ACTION;
2066 	}
2067 
2068 	return (rc > 0) ? dir_cfg->unauth_action : OIDC_DEFAULT_UNAUTH_ACTION;
2069 #else
2070 	return dir_cfg->unauth_action;
2071 #endif
2072 }
2073 
oidc_dir_cfg_unauth_expr_is_set(request_rec * r)2074 apr_byte_t oidc_dir_cfg_unauth_expr_is_set(request_rec *r) {
2075 #if MODULE_MAGIC_NUMBER_MAJOR >= 20100714
2076 	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
2077 			&auth_openidc_module);
2078 	return (dir_cfg->unauth_expression != NULL) ? TRUE : FALSE;
2079 #else
2080 	return FALSE;
2081 #endif
2082 }
2083 
oidc_dir_cfg_unautz_action(request_rec * r)2084 int oidc_dir_cfg_unautz_action(request_rec *r) {
2085 	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
2086 			&auth_openidc_module);
2087 	if (dir_cfg->unautz_action == OIDC_CONFIG_POS_INT_UNSET)
2088 		return OIDC_DEFAULT_UNAUTZ_ACTION;
2089 	return dir_cfg->unautz_action;
2090 }
2091 
oidc_dir_cfg_path_auth_request_params(request_rec * r)2092 char* oidc_dir_cfg_path_auth_request_params(request_rec *r) {
2093 	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
2094 			&auth_openidc_module);
2095 	return dir_cfg->path_auth_request_params;
2096 }
2097 
oidc_dir_cfg_path_scope(request_rec * r)2098 char* oidc_dir_cfg_path_scope(request_rec *r) {
2099 	oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
2100 			&auth_openidc_module);
2101 	return dir_cfg->path_scope;
2102 }
2103 
2104 /*
2105  * merge a new directory config with a base one
2106  */
oidc_merge_dir_config(apr_pool_t * pool,void * BASE,void * ADD)2107 void* oidc_merge_dir_config(apr_pool_t *pool, void *BASE, void *ADD) {
2108 	oidc_dir_cfg *c = apr_pcalloc(pool, sizeof(oidc_dir_cfg));
2109 	oidc_dir_cfg *base = BASE;
2110 	oidc_dir_cfg *add = ADD;
2111 	c->discover_url =
2112 			(apr_strnatcmp(add->discover_url, OIDC_CONFIG_STRING_UNSET) != 0) ?
2113 					add->discover_url : base->discover_url;
2114 	c->cookie =
2115 			(apr_strnatcmp(add->cookie, OIDC_CONFIG_STRING_UNSET) != 0) ?
2116 					add->cookie : base->cookie;
2117 	c->cookie_path =
2118 			(apr_strnatcmp(add->cookie_path, OIDC_CONFIG_STRING_UNSET) != 0) ?
2119 					add->cookie_path : base->cookie_path;
2120 	c->authn_header =
2121 			(apr_strnatcmp(add->authn_header, OIDC_CONFIG_STRING_UNSET) != 0) ?
2122 					add->authn_header : base->authn_header;
2123 	c->unauth_action =
2124 			add->unauth_action != OIDC_CONFIG_POS_INT_UNSET ?
2125 					add->unauth_action : base->unauth_action;
2126 #if MODULE_MAGIC_NUMBER_MAJOR >= 20100714
2127 	c->unauth_expression =
2128 			add->unauth_expression != NULL ?
2129 					add->unauth_expression : base->unauth_expression;
2130 #endif
2131 	c->unautz_action =
2132 			add->unautz_action != OIDC_CONFIG_POS_INT_UNSET ?
2133 					add->unautz_action : base->unautz_action;
2134 
2135 	c->pass_cookies =
2136 			add->pass_cookies != NULL ? add->pass_cookies : base->pass_cookies;
2137 	c->strip_cookies =
2138 			add->strip_cookies != NULL ?
2139 					add->strip_cookies : base->strip_cookies;
2140 
2141 	c->pass_info_in_headers =
2142 			add->pass_info_in_headers != OIDC_CONFIG_POS_INT_UNSET ?
2143 					add->pass_info_in_headers : base->pass_info_in_headers;
2144 	c->pass_info_in_env_vars =
2145 			add->pass_info_in_env_vars != OIDC_CONFIG_POS_INT_UNSET ?
2146 					add->pass_info_in_env_vars : base->pass_info_in_env_vars;
2147 	c->pass_info_base64url =
2148 			add->pass_info_base64url != OIDC_CONFIG_POS_INT_UNSET ?
2149 					add->pass_info_base64url : base->pass_info_base64url;
2150 	c->oauth_accept_token_in =
2151 			add->oauth_accept_token_in != OIDC_CONFIG_POS_INT_UNSET ?
2152 					add->oauth_accept_token_in : base->oauth_accept_token_in;
2153 	c->oauth_accept_token_options =
2154 			apr_hash_count(add->oauth_accept_token_options) > 0 ?
2155 					add->oauth_accept_token_options :
2156 					base->oauth_accept_token_options;
2157 	c->oauth_token_introspect_interval =
2158 			add->oauth_token_introspect_interval >= -1 ?
2159 					add->oauth_token_introspect_interval :
2160 					base->oauth_token_introspect_interval;
2161 	c->preserve_post =
2162 			add->preserve_post != OIDC_CONFIG_POS_INT_UNSET ?
2163 					add->preserve_post : base->preserve_post;
2164 	c->pass_refresh_token =
2165 			add->pass_refresh_token != OIDC_CONFIG_POS_INT_UNSET ?
2166 					add->pass_refresh_token : base->pass_refresh_token;
2167 	c->path_auth_request_params =
2168 			add->path_auth_request_params != NULL ?
2169 					add->path_auth_request_params :
2170 					base->path_auth_request_params;
2171 	c->path_scope =
2172 			add->path_scope != NULL ? add->path_scope : base->path_scope;
2173 
2174 	c->refresh_access_token_before_expiry =
2175 			add->refresh_access_token_before_expiry != OIDC_CONFIG_POS_INT_UNSET ?
2176 					add->refresh_access_token_before_expiry :
2177 					base->refresh_access_token_before_expiry;
2178 
2179 	c->logout_on_error_refresh =
2180 			add->logout_on_error_refresh != OIDC_CONFIG_POS_INT_UNSET ?
2181 					add->logout_on_error_refresh :
2182 					base->logout_on_error_refresh;
2183 
2184 	c->state_cookie_prefix =
2185 			(apr_strnatcmp(add->state_cookie_prefix, OIDC_CONFIG_STRING_UNSET)
2186 					!= 0) ?
2187 							add->state_cookie_prefix : base->state_cookie_prefix;
2188 
2189 	return (c);
2190 }
2191 
2192 /*
2193  * report a config error
2194  */
oidc_check_config_error(server_rec * s,const char * config_str)2195 static int oidc_check_config_error(server_rec *s, const char *config_str) {
2196 	oidc_serror(s, "mandatory parameter '%s' is not set", config_str);
2197 	return HTTP_INTERNAL_SERVER_ERROR;
2198 }
2199 
2200 /*
2201  * check the config required for the OpenID Connect RP role
2202  */
oidc_check_config_openid_openidc(server_rec * s,oidc_cfg * c)2203 static int oidc_check_config_openid_openidc(server_rec *s, oidc_cfg *c) {
2204 
2205 	apr_uri_t r_uri;
2206 	apr_byte_t redirect_uri_is_relative;
2207 
2208 	if ((c->metadata_dir == NULL) && (c->provider.issuer == NULL)
2209 			&& (c->provider.metadata_url == NULL)) {
2210 		oidc_serror(s,
2211 				"one of '" OIDCProviderIssuer "', '" OIDCProviderMetadataURL "' or '" OIDCMetadataDir "' must be set");
2212 		return HTTP_INTERNAL_SERVER_ERROR;
2213 	}
2214 
2215 	if (c->redirect_uri == NULL)
2216 		return oidc_check_config_error(s, OIDCRedirectURI);
2217 	redirect_uri_is_relative = (c->redirect_uri[0] == OIDC_CHAR_FORWARD_SLASH);
2218 
2219 	if (c->crypto_passphrase == NULL)
2220 		return oidc_check_config_error(s, OIDCCryptoPassphrase);
2221 
2222 	if (c->metadata_dir == NULL) {
2223 		if (c->provider.metadata_url == NULL) {
2224 			if (c->provider.issuer == NULL)
2225 				return oidc_check_config_error(s, OIDCProviderIssuer);
2226 			if (c->provider.authorization_endpoint_url == NULL)
2227 				return oidc_check_config_error(s,
2228 						OIDCProviderAuthorizationEndpoint);
2229 		} else {
2230 			apr_uri_parse(s->process->pconf, c->provider.metadata_url, &r_uri);
2231 			if ((r_uri.scheme == NULL)
2232 					|| (apr_strnatcmp(r_uri.scheme, "https") != 0)) {
2233 				oidc_swarn(s,
2234 						"the URL scheme (%s) of the configured " OIDCProviderMetadataURL " SHOULD be \"https\" for security reasons!",
2235 						r_uri.scheme);
2236 			}
2237 		}
2238 		if (c->provider.client_id == NULL)
2239 			return oidc_check_config_error(s, OIDCClientID);
2240 	} else {
2241 		if (c->provider.metadata_url != NULL) {
2242 			oidc_serror(s,
2243 					"only one of '" OIDCProviderMetadataURL "' or '" OIDCMetadataDir "' should be set");
2244 			return HTTP_INTERNAL_SERVER_ERROR;
2245 		}
2246 	}
2247 
2248 	apr_uri_parse(s->process->pconf, c->redirect_uri, &r_uri);
2249 	if (!redirect_uri_is_relative) {
2250 		if (apr_strnatcmp(r_uri.scheme, "https") != 0) {
2251 			oidc_swarn(s,
2252 					"the URL scheme (%s) of the configured " OIDCRedirectURI " SHOULD be \"https\" for security reasons (moreover: some Providers may reject non-HTTPS URLs)",
2253 					r_uri.scheme);
2254 		}
2255 	}
2256 
2257 	if (c->cookie_domain != NULL) {
2258 		if (redirect_uri_is_relative) {
2259 			oidc_swarn(s,
2260 					"if the configured " OIDCRedirectURI " is relative, " OIDCCookieDomain " SHOULD be empty");
2261 		} else if (!oidc_util_cookie_domain_valid(r_uri.hostname,
2262 				c->cookie_domain)) {
2263 			oidc_serror(s,
2264 					"the domain (%s) configured in " OIDCCookieDomain " does not match the URL hostname (%s) of the configured " OIDCRedirectURI " (%s): setting \"state\" and \"session\" cookies will not work!",
2265 					c->cookie_domain, r_uri.hostname, c->redirect_uri);
2266 			return HTTP_INTERNAL_SERVER_ERROR;
2267 		}
2268 	}
2269 
2270 	return OK;
2271 }
2272 
2273 /*
2274  * check the config required for the OAuth 2.0 RS role
2275  */
oidc_check_config_oauth(server_rec * s,oidc_cfg * c)2276 static int oidc_check_config_oauth(server_rec *s, oidc_cfg *c) {
2277 
2278 	apr_uri_t r_uri;
2279 
2280 	oidc_swarn(s,
2281 			"The OAuth 2.0 Resource Server functionality is deprecated and superseded by a new module, see: https://github.com/zmartzone/mod_oauth2!");
2282 
2283 	if (c->oauth.metadata_url != NULL) {
2284 		apr_uri_parse(s->process->pconf, c->oauth.metadata_url, &r_uri);
2285 		if ((r_uri.scheme == NULL)
2286 				|| (apr_strnatcmp(r_uri.scheme, "https") != 0)) {
2287 			oidc_swarn(s,
2288 					"the URL scheme (%s) of the configured " OIDCOAuthServerMetadataURL " SHOULD be \"https\" for security reasons!",
2289 					r_uri.scheme);
2290 		}
2291 		return OK;
2292 	}
2293 
2294 	if (c->oauth.introspection_endpoint_url == NULL) {
2295 
2296 		if ((c->oauth.verify_jwks_uri == NULL)
2297 				&& (c->oauth.verify_public_keys == NULL)
2298 				&& (c->oauth.verify_shared_keys == NULL)) {
2299 			oidc_serror(s,
2300 					"one of '" OIDCOAuthServerMetadataURL "', '" OIDCOAuthIntrospectionEndpoint "', '" OIDCOAuthVerifyJwksUri "', '" OIDCOAuthVerifySharedKeys "' or '" OIDCOAuthVerifyCertFiles "' must be set");
2301 			return HTTP_INTERNAL_SERVER_ERROR;
2302 		}
2303 
2304 	} else if ((c->oauth.verify_jwks_uri != NULL)
2305 			|| (c->oauth.verify_public_keys != NULL)
2306 			|| (c->oauth.verify_shared_keys != NULL)) {
2307 		oidc_serror(s,
2308 				"only '" OIDCOAuthIntrospectionEndpoint "' OR one (or more) out of ('" OIDCOAuthVerifyJwksUri "', '" OIDCOAuthVerifySharedKeys "' or '" OIDCOAuthVerifyCertFiles "') must be set");
2309 		return HTTP_INTERNAL_SERVER_ERROR;
2310 
2311 	}
2312 
2313 	if ((c->cache_encrypt == 1) && (c->crypto_passphrase == NULL))
2314 		return oidc_check_config_error(s, OIDCCryptoPassphrase);
2315 
2316 	return OK;
2317 }
2318 
2319 /*
2320  * check the config of a vhost
2321  */
oidc_config_check_vhost_config(apr_pool_t * pool,server_rec * s)2322 static int oidc_config_check_vhost_config(apr_pool_t *pool, server_rec *s) {
2323 	oidc_cfg *cfg = ap_get_module_config(s->module_config,
2324 			&auth_openidc_module);
2325 
2326 	oidc_sdebug(s, "enter");
2327 
2328 	if ((cfg->metadata_dir != NULL) || (cfg->provider.issuer != NULL)
2329 			|| (cfg->provider.metadata_url != NULL)) {
2330 		if (oidc_check_config_openid_openidc(s, cfg) != OK)
2331 			return HTTP_INTERNAL_SERVER_ERROR;
2332 	}
2333 
2334 	if ((cfg->oauth.metadata_url != NULL) || (cfg->oauth.client_id != NULL)
2335 			|| (cfg->oauth.client_secret != NULL)
2336 			|| (cfg->oauth.introspection_endpoint_url != NULL)
2337 			|| (cfg->oauth.verify_jwks_uri != NULL)
2338 			|| (cfg->oauth.verify_public_keys != NULL)
2339 			|| (cfg->oauth.verify_shared_keys != NULL)) {
2340 		if (oidc_check_config_oauth(s, cfg) != OK)
2341 			return HTTP_INTERNAL_SERVER_ERROR;
2342 	}
2343 
2344 	return OK;
2345 }
2346 
2347 /*
2348  * check the config of a merged vhost
2349  */
oidc_config_check_merged_vhost_configs(apr_pool_t * pool,server_rec * s)2350 static int oidc_config_check_merged_vhost_configs(apr_pool_t *pool,
2351 		server_rec *s) {
2352 	int status = OK;
2353 	while (s != NULL && status == OK) {
2354 		oidc_cfg *cfg = ap_get_module_config(s->module_config,
2355 				&auth_openidc_module);
2356 		if (cfg->merged) {
2357 			status = oidc_config_check_vhost_config(pool, s);
2358 		}
2359 		s = s->next;
2360 	}
2361 	return status;
2362 }
2363 
2364 /*
2365  * check if any merged vhost configs exist
2366  */
oidc_config_merged_vhost_configs_exist(server_rec * s)2367 static int oidc_config_merged_vhost_configs_exist(server_rec *s) {
2368 	while (s != NULL) {
2369 		oidc_cfg *cfg = ap_get_module_config(s->module_config,
2370 				&auth_openidc_module);
2371 		if (cfg->merged) {
2372 			return TRUE;
2373 		}
2374 		s = s->next;
2375 	}
2376 	return FALSE;
2377 }
2378 
2379 /*
2380  * SSL initialization magic copied from mod_auth_cas
2381  */
2382 #if ((OPENSSL_VERSION_NUMBER < 0x10100000) && defined(OPENSSL_THREADS) && APR_HAS_THREADS)
2383 
2384 static apr_thread_mutex_t **ssl_locks;
2385 static int ssl_num_locks;
2386 
oidc_ssl_locking_callback(int mode,int type,const char * file,int line)2387 static void oidc_ssl_locking_callback(int mode, int type, const char *file,
2388 		int line) {
2389 	if (type < ssl_num_locks) {
2390 		if (mode & CRYPTO_LOCK)
2391 			apr_thread_mutex_lock(ssl_locks[type]);
2392 		else
2393 			apr_thread_mutex_unlock(ssl_locks[type]);
2394 	}
2395 }
2396 
2397 #ifdef OPENSSL_NO_THREADID
oidc_ssl_id_callback(void)2398 static unsigned long oidc_ssl_id_callback(void) {
2399 	return (unsigned long) apr_os_thread_current();
2400 }
2401 #else
oidc_ssl_id_callback(CRYPTO_THREADID * id)2402 static void oidc_ssl_id_callback(CRYPTO_THREADID *id) {
2403 	CRYPTO_THREADID_set_numeric(id, (unsigned long) apr_os_thread_current());
2404 }
2405 #endif /* OPENSSL_NO_THREADID */
2406 
2407 #endif /* defined(OPENSSL_THREADS) && APR_HAS_THREADS */
2408 
oidc_cleanup_child(void * data)2409 static apr_status_t oidc_cleanup_child(void *data) {
2410 	server_rec *sp = (server_rec*) data;
2411 	while (sp != NULL) {
2412 		oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(sp->module_config,
2413 				&auth_openidc_module);
2414 		if (cfg->cache->destroy != NULL) {
2415 			if (cfg->cache->destroy(sp) != APR_SUCCESS) {
2416 				oidc_serror(sp, "cache destroy function failed");
2417 			}
2418 		}
2419 
2420 		// can do this even though we haven't got a deep copy
2421 		// since references within the object will be set to NULL
2422 		oidc_jwk_list_destroy_hash(sp->process->pool,
2423 				cfg->oauth.verify_public_keys);
2424 		oidc_jwk_list_destroy_hash(sp->process->pool,
2425 				cfg->oauth.verify_shared_keys);
2426 		oidc_jwk_list_destroy(sp->process->pool, cfg->public_keys);
2427 		oidc_jwk_list_destroy(sp->process->pool, cfg->private_keys);
2428 
2429 		sp = sp->next;
2430 	}
2431 
2432 	return APR_SUCCESS;
2433 }
2434 
oidc_cleanup_parent(void * data)2435 static apr_status_t oidc_cleanup_parent(void *data) {
2436 
2437 	oidc_cleanup_child(data);
2438 
2439 #if ((OPENSSL_VERSION_NUMBER < 0x10100000) && defined (OPENSSL_THREADS) && APR_HAS_THREADS)
2440 	if (CRYPTO_get_locking_callback() == oidc_ssl_locking_callback)
2441 		CRYPTO_set_locking_callback(NULL);
2442 #ifdef OPENSSL_NO_THREADID
2443 	if (CRYPTO_get_id_callback() == oidc_ssl_id_callback)
2444 		CRYPTO_set_id_callback(NULL);
2445 #else
2446 	if (CRYPTO_THREADID_get_callback() == oidc_ssl_id_callback)
2447 		CRYPTO_THREADID_set_callback(NULL);
2448 #endif /* OPENSSL_NO_THREADID */
2449 
2450 #endif /* (OPENSSL_VERSION_NUMBER < 0x10100000) && defined (OPENSSL_THREADS) && APR_HAS_THREADS */
2451 
2452 	EVP_cleanup();
2453 	curl_global_cleanup();
2454 
2455 	ap_log_error(APLOG_MARK, APLOG_INFO, 0, (server_rec* ) data,
2456 			"%s - shutdown", NAMEVERSION);
2457 
2458 	return APR_SUCCESS;
2459 }
2460 
2461 /*
2462  * handler that is called (twice) after the configuration phase; check if everything is OK
2463  */
oidc_post_config(apr_pool_t * pool,apr_pool_t * p1,apr_pool_t * p2,server_rec * s)2464 static int oidc_post_config(apr_pool_t *pool, apr_pool_t *p1, apr_pool_t *p2,
2465 		server_rec *s) {
2466 	const char *userdata_key = "oidc_post_config";
2467 	void *data = NULL;
2468 
2469 	/* Since the post_config hook is invoked twice (once
2470 	 * for 'sanity checking' of the config and once for
2471 	 * the actual server launch, we have to use a hack
2472 	 * to not run twice
2473 	 */
2474 	apr_pool_userdata_get(&data, userdata_key, s->process->pool);
2475 	if (data == NULL) {
2476 		apr_pool_userdata_set((const void*) 1, userdata_key,
2477 				apr_pool_cleanup_null, s->process->pool);
2478 		return OK;
2479 	}
2480 
2481 	ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
2482 			"%s - init - cjose %s, %s, EC=%s, GCM=%s, Memcache=%s, Redis=%s, JQ=%s",
2483 			NAMEVERSION, cjose_version(), OPENSSL_VERSION_TEXT,
2484 			OIDC_JOSE_EC_SUPPORT ? "yes" : "no",
2485 					OIDC_JOSE_GCM_SUPPORT ? "yes" : "no",
2486 #ifdef USE_MEMCACHE
2487 							"yes"
2488 #else
2489 							"no"
2490 #endif
2491 							,
2492 #ifdef USE_LIBHIREDIS
2493 							"yes"
2494 #else
2495 							"no"
2496 #endif
2497 							,
2498 #ifdef USE_LIBJQ
2499 							"yes"
2500 #else
2501 							"no"
2502 #endif
2503 	);
2504 
2505 	curl_global_init(CURL_GLOBAL_ALL);
2506 	OpenSSL_add_all_digests();
2507 
2508 #if ((OPENSSL_VERSION_NUMBER < 0x10100000) && defined (OPENSSL_THREADS) && APR_HAS_THREADS)
2509 	ssl_num_locks = CRYPTO_num_locks();
2510 	ssl_locks = apr_pcalloc(s->process->pool,
2511 			ssl_num_locks * sizeof(*ssl_locks));
2512 
2513 	int i;
2514 	for (i = 0; i < ssl_num_locks; i++)
2515 		apr_thread_mutex_create(&(ssl_locks[i]), APR_THREAD_MUTEX_DEFAULT,
2516 				s->process->pool);
2517 
2518 #ifdef OPENSSL_NO_THREADID
2519 	if (CRYPTO_get_locking_callback() == NULL && CRYPTO_get_id_callback() == NULL) {
2520 		CRYPTO_set_locking_callback(oidc_ssl_locking_callback);
2521 		CRYPTO_set_id_callback(oidc_ssl_id_callback);
2522 	}
2523 #else
2524 	if (CRYPTO_get_locking_callback() == NULL
2525 			&& CRYPTO_THREADID_get_callback() == NULL) {
2526 		CRYPTO_set_locking_callback(oidc_ssl_locking_callback);
2527 		CRYPTO_THREADID_set_callback(oidc_ssl_id_callback);
2528 	}
2529 #endif /* OPENSSL_NO_THREADID */
2530 
2531 #endif /* (OPENSSL_VERSION_NUMBER < 0x10100000) && defined (OPENSSL_THREADS) && APR_HAS_THREADS */
2532 
2533 	apr_pool_cleanup_register(pool, s, oidc_cleanup_parent,
2534 			apr_pool_cleanup_null);
2535 
2536 	server_rec *sp = s;
2537 	while (sp != NULL) {
2538 		oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(sp->module_config,
2539 				&auth_openidc_module);
2540 		if (cfg->cache->post_config != NULL) {
2541 			if (cfg->cache->post_config(sp) != OK)
2542 				return HTTP_INTERNAL_SERVER_ERROR;
2543 		}
2544 		sp = sp->next;
2545 	}
2546 
2547 	/*
2548 	 * Apache has a base vhost that true vhosts derive from.
2549 	 * There are two startup scenarios:
2550 	 *
2551 	 * 1. Only the base vhost contains OIDC settings.
2552 	 *    No server configs have been merged.
2553 	 *    Only the base vhost needs to be checked.
2554 	 *
2555 	 * 2. The base vhost contains zero or more OIDC settings.
2556 	 *    One or more vhosts override these.
2557 	 *    These vhosts have a merged config.
2558 	 *    All merged configs need to be checked.
2559 	 */
2560 	if (!oidc_config_merged_vhost_configs_exist(s)) {
2561 		/* nothing merged, only check the base vhost */
2562 		return oidc_config_check_vhost_config(pool, s);
2563 	}
2564 	return oidc_config_check_merged_vhost_configs(pool, s);
2565 }
2566 
2567 #if MODULE_MAGIC_NUMBER_MAJOR >= 20100714
oidc_parse_config(cmd_parms * cmd,const char * require_line,const void ** parsed_require_line)2568 static const char* oidc_parse_config(cmd_parms *cmd, const char *require_line,
2569 		const void **parsed_require_line) {
2570 	const char *expr_err = NULL;
2571 	ap_expr_info_t *expr;
2572 
2573 	expr = ap_expr_parse_cmd(cmd, require_line, AP_EXPR_FLAG_STRING_RESULT,
2574 			&expr_err, NULL);
2575 
2576 	if (expr_err)
2577 		return apr_pstrcat(cmd->temp_pool,
2578 				"Cannot parse expression in require line: ", expr_err, NULL);
2579 
2580 	*parsed_require_line = expr;
2581 
2582 	return NULL;
2583 }
2584 
2585 static const authz_provider oidc_authz_claim_provider = {
2586 		&oidc_authz_checker_claim, &oidc_parse_config, };
2587 #ifdef USE_LIBJQ
2588 static const authz_provider oidc_authz_claims_expr_provider = {
2589 		&oidc_authz_checker_claims_expr,
2590 		NULL,
2591 };
2592 #endif
2593 #endif
2594 
2595 /*
2596  * initialize cache context in child process if required
2597  */
oidc_child_init(apr_pool_t * p,server_rec * s)2598 static void oidc_child_init(apr_pool_t *p, server_rec *s) {
2599 	server_rec *sp = s;
2600 	while (sp != NULL) {
2601 		oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(sp->module_config,
2602 				&auth_openidc_module);
2603 		if (cfg->cache->child_init != NULL) {
2604 			if (cfg->cache->child_init(p, sp) != APR_SUCCESS) {
2605 				oidc_serror(sp, "cfg->cache->child_init failed");
2606 			}
2607 		}
2608 		sp = sp->next;
2609 	}
2610 	apr_pool_cleanup_register(p, s, oidc_cleanup_child, apr_pool_cleanup_null);
2611 }
2612 
2613 static const char oidcFilterName[] = "oidc_filter_in_filter";
2614 
oidc_filter_in_insert_filter(request_rec * r)2615 static void oidc_filter_in_insert_filter(request_rec *r) {
2616 
2617 	if (oidc_enabled(r) == FALSE)
2618 		return;
2619 
2620 	if (ap_is_initial_req(r) == 0)
2621 		return;
2622 
2623 	apr_table_t *userdata_post_params = NULL;
2624 	apr_pool_userdata_get((void**) &userdata_post_params,
2625 			OIDC_USERDATA_POST_PARAMS_KEY, r->pool);
2626 	if (userdata_post_params == NULL)
2627 		return;
2628 
2629 	ap_add_input_filter(oidcFilterName, NULL, r, r->connection);
2630 }
2631 
2632 typedef struct oidc_filter_in_context {
2633 	apr_bucket_brigade *pbbTmp;
2634 	apr_size_t nbytes;
2635 } oidc_filter_in_context;
2636 
oidc_filter_in_filter(ap_filter_t * f,apr_bucket_brigade * brigade,ap_input_mode_t mode,apr_read_type_e block,apr_off_t nbytes)2637 static apr_status_t oidc_filter_in_filter(ap_filter_t *f,
2638 		apr_bucket_brigade *brigade, ap_input_mode_t mode,
2639 		apr_read_type_e block, apr_off_t nbytes) {
2640 	oidc_filter_in_context *ctx = NULL;
2641 	apr_bucket *b_in = NULL, *b_out = NULL;
2642 	char *buf = NULL;
2643 	apr_table_t *userdata_post_params = NULL;
2644 	apr_status_t rc = APR_SUCCESS;
2645 
2646 	if (!(ctx = f->ctx)) {
2647 		f->ctx = ctx = apr_palloc(f->r->pool, sizeof *ctx);
2648 		ctx->pbbTmp = apr_brigade_create(f->r->pool,
2649 				f->r->connection->bucket_alloc);
2650 		ctx->nbytes = 0;
2651 	}
2652 
2653 	if (APR_BRIGADE_EMPTY(ctx->pbbTmp)) {
2654 		rc = ap_get_brigade(f->next, ctx->pbbTmp, mode, block, nbytes);
2655 
2656 		if (mode == AP_MODE_EATCRLF || rc != APR_SUCCESS)
2657 			return rc;
2658 	}
2659 
2660 	while (!APR_BRIGADE_EMPTY(ctx->pbbTmp)) {
2661 
2662 		b_in = APR_BRIGADE_FIRST(ctx->pbbTmp);
2663 
2664 		if (APR_BUCKET_IS_EOS(b_in)) {
2665 
2666 			APR_BUCKET_REMOVE(b_in);
2667 
2668 			apr_pool_userdata_get((void**) &userdata_post_params,
2669 					OIDC_USERDATA_POST_PARAMS_KEY, f->r->pool);
2670 
2671 			if (userdata_post_params != NULL) {
2672 				buf = apr_psprintf(f->r->pool, "%s%s",
2673 						ctx->nbytes > 0 ? "&" : "",
2674 								oidc_util_http_form_encoded_data(f->r,
2675 										userdata_post_params));
2676 				b_out = apr_bucket_heap_create(buf, strlen(buf), 0,
2677 						f->r->connection->bucket_alloc);
2678 
2679 				APR_BRIGADE_INSERT_TAIL(brigade, b_out);
2680 
2681 				ctx->nbytes += strlen(buf);
2682 
2683 				if (oidc_util_hdr_in_content_length_get(f->r) != NULL)
2684 					oidc_util_hdr_in_set(f->r, OIDC_HTTP_HDR_CONTENT_LENGTH,
2685 							apr_psprintf(f->r->pool, "%ld", ctx->nbytes));
2686 
2687 				apr_pool_userdata_set(NULL, OIDC_USERDATA_POST_PARAMS_KEY,
2688 						NULL, f->r->pool);
2689 			}
2690 
2691 			APR_BRIGADE_INSERT_TAIL(brigade, b_in);
2692 
2693 			break;
2694 		}
2695 
2696 		APR_BUCKET_REMOVE(b_in);
2697 		APR_BRIGADE_INSERT_TAIL(brigade, b_in);
2698 		ctx->nbytes += b_in->length;
2699 	}
2700 
2701 	return rc;
2702 }
2703 
2704 /*
2705  * register our authentication and authorization functions
2706  */
oidc_register_hooks(apr_pool_t * pool)2707 void oidc_register_hooks(apr_pool_t *pool) {
2708 	ap_hook_post_config(oidc_post_config, NULL, NULL, APR_HOOK_LAST);
2709 	ap_hook_child_init(oidc_child_init, NULL, NULL, APR_HOOK_MIDDLE);
2710 	ap_hook_handler(oidc_content_handler, NULL, NULL, APR_HOOK_FIRST);
2711 	ap_hook_insert_filter(oidc_filter_in_insert_filter, NULL, NULL,
2712 			APR_HOOK_MIDDLE);
2713 	ap_register_input_filter(oidcFilterName, oidc_filter_in_filter, NULL,
2714 			AP_FTYPE_RESOURCE);
2715 #if MODULE_MAGIC_NUMBER_MAJOR >= 20100714
2716 	ap_hook_check_authn(oidc_check_user_id, NULL, NULL, APR_HOOK_MIDDLE,
2717 			AP_AUTH_INTERNAL_PER_CONF);
2718 	ap_register_auth_provider(pool, AUTHZ_PROVIDER_GROUP,
2719 			OIDC_REQUIRE_CLAIM_NAME, "0", &oidc_authz_claim_provider,
2720 			AP_AUTH_INTERNAL_PER_CONF);
2721 #ifdef USE_LIBJQ
2722 	ap_register_auth_provider(pool, AUTHZ_PROVIDER_GROUP,
2723 			OIDC_REQUIRE_CLAIMS_EXPR_NAME, "0",
2724 			&oidc_authz_claims_expr_provider, AP_AUTH_INTERNAL_PER_CONF);
2725 #endif
2726 #else
2727 	static const char * const authzSucc[] = {"mod_authz_user.c", NULL};
2728 	ap_hook_check_user_id(oidc_check_user_id, NULL, NULL, APR_HOOK_MIDDLE);
2729 	ap_hook_auth_checker(oidc_auth_checker, NULL, authzSucc, APR_HOOK_MIDDLE);
2730 #endif
2731 }
2732 
2733 /*
2734  * set of configuration primitives
2735  */
2736 const command_rec oidc_config_cmds[] = {
2737 
2738 		AP_INIT_TAKE1(OIDCProviderMetadataURL,
2739 				oidc_set_url_slot,
2740 				(void*)APR_OFFSETOF(oidc_cfg, provider.metadata_url),
2741 				RSRC_CONF,
2742 				"OpenID Connect OP configuration metadata URL."),
2743 		AP_INIT_TAKE1(OIDCProviderIssuer,
2744 				oidc_set_string_slot,
2745 				(void*)APR_OFFSETOF(oidc_cfg, provider.issuer),
2746 				RSRC_CONF,
2747 				"OpenID Connect OP issuer identifier."),
2748 		AP_INIT_TAKE1(OIDCProviderAuthorizationEndpoint,
2749 				oidc_set_https_slot,
2750 				(void *)APR_OFFSETOF(oidc_cfg, provider.authorization_endpoint_url),
2751 				RSRC_CONF,
2752 				"Define the OpenID OP Authorization Endpoint URL (e.g.: https://localhost:9031/as/authorization.oauth2)"),
2753 		AP_INIT_TAKE1(OIDCProviderTokenEndpoint,
2754 				oidc_set_https_slot,
2755 				(void *)APR_OFFSETOF(oidc_cfg, provider.token_endpoint_url),
2756 				RSRC_CONF,
2757 				"Define the OpenID OP Token Endpoint URL (e.g.: https://localhost:9031/as/token.oauth2)"),
2758 		AP_INIT_TAKE1(OIDCProviderTokenEndpointAuth,
2759 				oidc_set_endpoint_auth_slot,
2760 				(void *)APR_OFFSETOF(oidc_cfg, provider.token_endpoint_auth),
2761 				RSRC_CONF,
2762 				"Specify an authentication method for the OpenID OP Token Endpoint (e.g.: client_secret_basic)"),
2763 		AP_INIT_TAKE1(OIDCProviderTokenEndpointParams,
2764 				oidc_set_string_slot,
2765 				(void *)APR_OFFSETOF(oidc_cfg, provider.token_endpoint_params),
2766 				RSRC_CONF,
2767 				"Define extra parameters that will be posted to the OpenID OP Token Endpoint (e.g.: param1=value1&param2=value2, all urlencoded)."),
2768 		AP_INIT_TAKE1(OIDCProviderRegistrationEndpointJson,
2769 				oidc_set_string_slot,
2770 				(void *)APR_OFFSETOF(oidc_cfg, provider.registration_endpoint_json),
2771 				RSRC_CONF,
2772 				"Define a JSON object with parameters that will be merged into the client registration request to the OpenID OP Registration Endpoint (e.g.: { \"request_uris\" : [ \"https://example.com/uri\"] })."),
2773 		AP_INIT_TAKE1(OIDCProviderUserInfoEndpoint,
2774 				oidc_set_https_slot,
2775 				(void *)APR_OFFSETOF(oidc_cfg, provider.userinfo_endpoint_url),
2776 				RSRC_CONF,
2777 				"Define the OpenID OP UserInfo Endpoint URL (e.g.: https://localhost:9031/idp/userinfo.openid)"),
2778 		AP_INIT_TAKE1(OIDCProviderRevocationEndpoint,
2779 				oidc_set_https_slot,
2780 				(void *)APR_OFFSETOF(oidc_cfg, provider.revocation_endpoint_url),
2781 				RSRC_CONF,
2782 				"Define the RFC 7009 Token Revocation Endpoint URL (e.g.: https://localhost:9031/as/revoke_token.oauth2)"),
2783 		AP_INIT_TAKE1(OIDCProviderCheckSessionIFrame,
2784 				oidc_set_url_slot,
2785 				(void *)APR_OFFSETOF(oidc_cfg, provider.check_session_iframe),
2786 				RSRC_CONF,
2787 				"Define the OpenID OP Check Session iFrame URL."),
2788 		AP_INIT_TAKE1(OIDCProviderEndSessionEndpoint,
2789 				oidc_set_url_slot,
2790 				(void *)APR_OFFSETOF(oidc_cfg, provider.end_session_endpoint),
2791 				RSRC_CONF,
2792 				"Define the OpenID OP End Session Endpoint URL."),
2793 		AP_INIT_FLAG(OIDCProviderBackChannelLogoutSupported,
2794 				oidc_set_flag_slot,
2795 				(void *)APR_OFFSETOF(oidc_cfg, provider.backchannel_logout_supported),
2796 				RSRC_CONF,
2797 				"Define whether the OP supports OpenID Connect Back Channel Logout."),
2798 		AP_INIT_TAKE1(OIDCProviderJwksUri,
2799 				oidc_set_https_slot,
2800 				(void *)APR_OFFSETOF(oidc_cfg, provider.jwks_uri),
2801 				RSRC_CONF,
2802 				"Define the OpenID OP JWKS URL (e.g.: https://localhost:9031/pf/JWKS)"),
2803 		AP_INIT_TAKE1(OIDCResponseType,
2804 				oidc_set_response_type,
2805 				(void *)APR_OFFSETOF(oidc_cfg, provider.response_type),
2806 				RSRC_CONF,
2807 				"The response type (or OpenID Connect Flow) used; must be one of \"code\", \"id_token\", \"id_token token\", \"code id_token\", \"code token\" or \"code id_token token\" (serves as default value for discovered OPs too)"),
2808 		AP_INIT_TAKE1(OIDCResponseMode,
2809 				oidc_set_response_mode,
2810 				(void *)APR_OFFSETOF(oidc_cfg, provider.response_mode),
2811 				RSRC_CONF,
2812 				"The response mode used; must be one of \"fragment\", \"query\" or \"form_post\" (serves as default value for discovered OPs too)"),
2813 
2814 		AP_INIT_ITERATE(OIDCPublicKeyFiles,
2815 				oidc_set_public_key_files,
2816 				(void *)APR_OFFSETOF(oidc_cfg, public_keys),
2817 				RSRC_CONF,
2818 				"The fully qualified names of the files that contain the RSA public keys or X.509 certificates that contains the RSA public keys that can be used for signature validation or encryption by the OP."),
2819 		AP_INIT_ITERATE(OIDCPrivateKeyFiles,
2820 				oidc_set_private_key_files_enc,
2821 				NULL,
2822 				RSRC_CONF,
2823 				"The fully qualified names of the files that contain the RSA private keys that can be used to decrypt content sent to us by the OP."),
2824 
2825 		AP_INIT_TAKE1(OIDCClientJwksUri,
2826 				oidc_set_https_slot,
2827 				(void *)APR_OFFSETOF(oidc_cfg, provider.client_jwks_uri),
2828 				RSRC_CONF,
2829 				"Define the Client JWKS URL (e.g.: https://localhost/protected/?jwks=rsa)"),
2830 		AP_INIT_TAKE1(OIDCIDTokenSignedResponseAlg,
2831 				oidc_set_signed_response_alg,
2832 				(void *)APR_OFFSETOF(oidc_cfg, provider.id_token_signed_response_alg),
2833 				RSRC_CONF,
2834 				"The algorithm that the OP must use to sign the ID token."),
2835 		AP_INIT_TAKE1(OIDCIDTokenEncryptedResponseAlg,
2836 				oidc_set_encrypted_response_alg,
2837 				(void *)APR_OFFSETOF(oidc_cfg, provider.id_token_encrypted_response_alg),
2838 				RSRC_CONF,
2839 				"The algorithm that the OP should use to encrypt the Content Encryption Key that is used to encrypt the id_token (used only in dynamic client registration); must be one of [RSA1_5|A128KW|A256KW|RSA-OAEP]"),
2840 		AP_INIT_TAKE1(OIDCIDTokenEncryptedResponseEnc,
2841 				oidc_set_encrypted_response_enc,
2842 				(void *)APR_OFFSETOF(oidc_cfg, provider.id_token_encrypted_response_enc),
2843 				RSRC_CONF,
2844 				"The algorithm that the OP should use to encrypt to the id_token with the Content Encryption Key (used only in dynamic client registration); must be one of [A128CBC-HS256|A256CBC-HS512|A256GCM]"),
2845 		AP_INIT_TAKE1(OIDCUserInfoSignedResponseAlg,
2846 				oidc_set_signed_response_alg,
2847 				(void *)APR_OFFSETOF(oidc_cfg, provider.userinfo_signed_response_alg),
2848 				RSRC_CONF,
2849 				"The algorithm that the OP should use to sign the UserInfo response (used only in dynamic client registration); must be one of [RS256|RS384|RS512|PS256|PS384|PS512|HS256|HS384|HS512]"),
2850 		AP_INIT_TAKE1(OIDCUserInfoEncryptedResponseAlg,
2851 				oidc_set_encrypted_response_alg,
2852 				(void *)APR_OFFSETOF(oidc_cfg, provider.userinfo_encrypted_response_alg),
2853 				RSRC_CONF,
2854 				"The algorithm that the OP should use to encrypt the Content Encryption Key that is used to encrypt the UserInfo response (used only in dynamic client registration); must be one of [RSA1_5|A128KW|A256KW|RSA-OAEP]"),
2855 		AP_INIT_TAKE1(OIDCUserInfoEncryptedResponseEnc,
2856 				oidc_set_encrypted_response_enc,
2857 				(void *)APR_OFFSETOF(oidc_cfg, provider.userinfo_encrypted_response_enc),
2858 				RSRC_CONF,
2859 				"The algorithm that the OP should use to encrypt to encrypt the UserInfo response with the Content Encryption Key (used only in dynamic client registration); must be one of [A128CBC-HS256|A256CBC-HS512|A256GCM]"),
2860 		AP_INIT_TAKE1(OIDCUserInfoTokenMethod,
2861 				oidc_set_userinfo_token_method,
2862 				(void *)APR_OFFSETOF(oidc_cfg, provider.userinfo_token_method),
2863 				RSRC_CONF,
2864 				"The method that is used to present the access token to the userinfo endpoint; must be one of [authz_header|post_param]"),
2865 		AP_INIT_TAKE1(OIDCTokenBindingPolicy,
2866 				oidc_set_token_binding_policy,
2867 				(void *)APR_OFFSETOF(oidc_cfg, provider.token_binding_policy),
2868 				RSRC_CONF,
2869 				"The token binding policy used with the provider; must be one of [disabled|optional|required|enforced]"),
2870 
2871 		AP_INIT_TAKE1(OIDCSSLValidateServer,
2872 				oidc_set_ssl_validate_slot,
2873 				(void*)APR_OFFSETOF(oidc_cfg, provider.ssl_validate_server),
2874 				RSRC_CONF,
2875 				"Require validation of the OpenID Connect OP SSL server certificate for successful authentication (On or Off)"),
2876 		AP_INIT_TAKE1(OIDCValidateIssuer,
2877 				oidc_set_validate_issuer_slot,
2878 				(void*)APR_OFFSETOF(oidc_cfg, provider.validate_issuer),
2879 				RSRC_CONF,
2880 				"Require validation of token issuer for successful authentication  (On or Off)"),
2881 		AP_INIT_TAKE1(OIDCClientName,
2882 				oidc_set_string_slot,
2883 				(void *) APR_OFFSETOF(oidc_cfg, provider.client_name),
2884 				RSRC_CONF,
2885 				"Define the (client_name) name that the client uses for dynamic registration to the OP."),
2886 		AP_INIT_TAKE1(OIDCClientContact,
2887 				oidc_set_string_slot,
2888 				(void *) APR_OFFSETOF(oidc_cfg, provider.client_contact),
2889 				RSRC_CONF,
2890 				"Define the contact that the client registers in dynamic registration with the OP."),
2891 		AP_INIT_TAKE1(OIDCScope,
2892 				oidc_set_string_slot,
2893 				(void *) APR_OFFSETOF(oidc_cfg, provider.scope),
2894 				RSRC_CONF,
2895 				"Define the OpenID Connect scope that is requested from the OP."),
2896 		AP_INIT_TAKE1(OIDCPathScope,
2897 				ap_set_string_slot,
2898 				(void*)APR_OFFSETOF(oidc_dir_cfg, path_scope),
2899 				RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
2900 				"Define the OpenID Connect scope that is requested from all providers for a specific path/context."),
2901 		AP_INIT_TAKE1(OIDCJWKSRefreshInterval,
2902 				oidc_set_jwks_refresh_interval,
2903 				(void*)APR_OFFSETOF(oidc_cfg, provider.jwks_refresh_interval),
2904 				RSRC_CONF,
2905 				"Duration in seconds after which retrieved JWS should be refreshed."),
2906 		AP_INIT_TAKE1(OIDCIDTokenIatSlack,
2907 				oidc_set_idtoken_iat_slack,
2908 				(void*)APR_OFFSETOF(oidc_cfg, provider.idtoken_iat_slack),
2909 				RSRC_CONF,
2910 				"Acceptable offset (both before and after) for checking the \"iat\" (= issued at) timestamp in the id_token."),
2911 		AP_INIT_TAKE1(OIDCSessionMaxDuration,
2912 				oidc_set_session_max_duration,
2913 				(void*)APR_OFFSETOF(oidc_cfg, provider.session_max_duration),
2914 				RSRC_CONF,
2915 				"Maximum duration of a session in seconds."),
2916 		AP_INIT_TAKE1(OIDCAuthRequestParams,
2917 				oidc_set_string_slot,
2918 				(void*)APR_OFFSETOF(oidc_cfg, provider.auth_request_params),
2919 				RSRC_CONF,
2920 				"Extra parameters that need to be sent in the Authorization Request (must be query-encoded like \"display=popup&prompt=consent\"."),
2921 		AP_INIT_TAKE1(OIDCPathAuthRequestParams,
2922 				ap_set_string_slot,
2923 				(void*)APR_OFFSETOF(oidc_dir_cfg, path_auth_request_params),
2924 				RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
2925 				"Extra parameters that need to be sent in the Authorization Request (must be query-encoded like \"display=popup&prompt=consent\"."),
2926 		AP_INIT_TAKE1(OIDCPKCEMethod,
2927 				oidc_set_pkce_method,
2928 				(void *)APR_OFFSETOF(oidc_cfg, provider.pkce),
2929 				RSRC_CONF,
2930 				"The RFC 7636 PCKE mode used; must be one of \"plain\", \"S256\" or \"referred_tb\""),
2931 
2932 		AP_INIT_TAKE1(OIDCClientID,
2933 				oidc_set_string_slot,
2934 				(void*)APR_OFFSETOF(oidc_cfg, provider.client_id),
2935 				RSRC_CONF,
2936 				"Client identifier used in calls to OpenID Connect OP."),
2937 		AP_INIT_TAKE1(OIDCClientSecret,
2938 				oidc_set_string_slot,
2939 				(void*)APR_OFFSETOF(oidc_cfg, provider.client_secret),
2940 				RSRC_CONF,
2941 				"Client secret used in calls to OpenID Connect OP."),
2942 
2943 		AP_INIT_TAKE1(OIDCClientTokenEndpointCert,
2944 				oidc_set_string_slot,
2945 				(void*)APR_OFFSETOF(oidc_cfg, provider.token_endpoint_tls_client_cert),
2946 				RSRC_CONF,
2947 				"TLS client certificate used for calls to OpenID Connect OP token endpoint."),
2948 		AP_INIT_TAKE1(OIDCClientTokenEndpointKey,
2949 				oidc_set_string_slot,
2950 				(void*)APR_OFFSETOF(oidc_cfg, provider.token_endpoint_tls_client_key),
2951 				RSRC_CONF,
2952 				"TLS client certificate private key used for calls to OpenID Connect OP token endpoint."),
2953 
2954 		AP_INIT_TAKE1(OIDCRedirectURI,
2955 				oidc_set_relative_or_absolute_url_slot,
2956 				(void *)APR_OFFSETOF(oidc_cfg, redirect_uri),
2957 				RSRC_CONF,
2958 				"Define the Redirect URI (e.g.: https://localhost:9031/protected/example/)"),
2959 		AP_INIT_TAKE1(OIDCDefaultURL,
2960 				oidc_set_url_slot,
2961 				(void *)APR_OFFSETOF(oidc_cfg, default_sso_url),
2962 				RSRC_CONF,
2963 				"Defines the default URL where the user is directed to in case of 3rd-party initiated SSO."),
2964 		AP_INIT_TAKE1(OIDCDefaultLoggedOutURL,
2965 				oidc_set_url_slot,
2966 				(void *)APR_OFFSETOF(oidc_cfg, default_slo_url),
2967 				RSRC_CONF,
2968 				"Defines the default URL where the user is directed to after logout."),
2969 		AP_INIT_TAKE1(OIDCCookieDomain,
2970 				oidc_set_cookie_domain,
2971 				NULL,
2972 				RSRC_CONF,
2973 				"Specify domain element for OIDC session cookie."),
2974 		AP_INIT_FLAG(OIDCCookieHTTPOnly,
2975 				oidc_set_flag_slot,
2976 				(void *) APR_OFFSETOF(oidc_cfg, cookie_http_only),
2977 				RSRC_CONF,
2978 				"Defines whether or not the cookie httponly flag is set on cookies."),
2979 		AP_INIT_FLAG(OIDCCookieSameSite,
2980 				oidc_set_flag_slot,
2981 				(void *) APR_OFFSETOF(oidc_cfg, cookie_same_site),
2982 				RSRC_CONF,
2983 				"Defines whether or not the cookie Same-Site flag is set on cookies."),
2984 		AP_INIT_TAKE1(OIDCOutgoingProxy,
2985 				oidc_set_string_slot,
2986 				(void*)APR_OFFSETOF(oidc_cfg, outgoing_proxy),
2987 				RSRC_CONF,
2988 				"Specify an outgoing proxy for your network (<host>[:<port>]."),
2989 		AP_INIT_TAKE1(OIDCCryptoPassphrase,
2990 				oidc_set_passphrase_slot,
2991 				(void*)APR_OFFSETOF(oidc_cfg, crypto_passphrase),
2992 				RSRC_CONF,
2993 				"Passphrase used for AES crypto on cookies and state."),
2994 		AP_INIT_TAKE1(OIDCClaimDelimiter,
2995 				oidc_set_string_slot,
2996 				(void*)APR_OFFSETOF(oidc_cfg, claim_delimiter),
2997 				RSRC_CONF,
2998 				"The delimiter to use when setting multi-valued claims in the HTTP headers."),
2999 		AP_INIT_RAW_ARGS(OIDCClaimPrefix,
3000 				oidc_cfg_set_claim_prefix,
3001 				(void*)APR_OFFSETOF(oidc_cfg, claim_prefix),
3002 				RSRC_CONF,
3003 				"The prefix to use when setting claims in the HTTP headers."),
3004 		AP_INIT_TAKE123(OIDCRemoteUserClaim,
3005 				oidc_set_remote_user_claim,
3006 				(void*)APR_OFFSETOF(oidc_cfg, remote_user_claim),
3007 				RSRC_CONF,
3008 				"The claim that is used when setting the REMOTE_USER variable for OpenID Connect protected paths."),
3009 		AP_INIT_TAKE123(OIDCPassIDTokenAs,
3010 				oidc_set_pass_idtoken_as,
3011 				NULL,
3012 				RSRC_CONF,
3013 				"The format in which the id_token is passed in (a) header(s); must be one or more of: claims|payload|serialized"),
3014 		AP_INIT_TAKE123(OIDCPassUserInfoAs,
3015 				oidc_set_pass_userinfo_as,
3016 				NULL,
3017 				RSRC_CONF,
3018 				"The format in which the userinfo is passed in (a) header(s); must be one or more of: claims|json|jwt"),
3019 
3020 		AP_INIT_TAKE1(OIDCOAuthClientID,
3021 				oidc_set_string_slot,
3022 				(void*)APR_OFFSETOF(oidc_cfg, oauth.client_id),
3023 				RSRC_CONF,
3024 				"Client identifier used in calls to OAuth 2.0 Authorization server validation calls."),
3025 		AP_INIT_TAKE1(OIDCOAuthClientSecret,
3026 				oidc_set_string_slot,
3027 				(void*)APR_OFFSETOF(oidc_cfg, oauth.client_secret),
3028 				RSRC_CONF,
3029 				"Client secret used in calls to OAuth 2.0 Authorization server validation calls."),
3030 
3031 		AP_INIT_TAKE1(OIDCOAuthIntrospectionEndpoint,
3032 				oidc_set_https_slot,
3033 				(void *)APR_OFFSETOF(oidc_cfg, oauth.introspection_endpoint_url),
3034 				RSRC_CONF,
3035 				"Define the OAuth AS Introspection Endpoint URL (e.g.: https://localhost:9031/as/token.oauth2)"),
3036 		AP_INIT_TAKE1(OIDCOAuthIntrospectionEndpointMethod,
3037 				oidc_set_introspection_method,
3038 				(void *)APR_OFFSETOF(oidc_cfg, oauth.introspection_endpoint_method),
3039 				RSRC_CONF,
3040 				"Define the HTTP method to use for the introspection call: one of \"GET\" or \"POST\" (default)"),
3041 		AP_INIT_TAKE1(OIDCOAuthIntrospectionEndpointParams,
3042 				oidc_set_string_slot,
3043 				(void*)APR_OFFSETOF(oidc_cfg, oauth.introspection_endpoint_params),
3044 				RSRC_CONF,
3045 				"Extra parameters that need to be sent in the token introspection request (must be query-encoded like \"grant_type=urn%3Apingidentity.com%3Aoauth2%3Agrant_type%3Avalidate_bearer\"."),
3046 
3047 		AP_INIT_TAKE1(OIDCOAuthIntrospectionEndpointAuth,
3048 				oidc_set_endpoint_auth_slot,
3049 				(void *)APR_OFFSETOF(oidc_cfg, oauth.introspection_endpoint_auth),
3050 				RSRC_CONF,
3051 				"Specify an authentication method for the OAuth AS Introspection Endpoint (e.g.: client_secret_basic)"),
3052         AP_INIT_RAW_ARGS(OIDCOAuthIntrospectionClientAuthBearerToken,
3053 				oidc_set_client_auth_bearer_token,
3054 				NULL,
3055 				RSRC_CONF,
3056 				"Specify a bearer token to authorize against the OAuth AS Introspection Endpoint (e.g.: 55554ee-2491-11e3-be72-001fe2e44345 or empty to use the introspected token itself)"),
3057 		AP_INIT_TAKE1(OIDCOAuthIntrospectionEndpointCert,
3058 				oidc_set_string_slot,
3059 				(void*)APR_OFFSETOF(oidc_cfg, oauth.introspection_endpoint_tls_client_cert),
3060 				RSRC_CONF,
3061 				"TLS client certificate used for calls to the OAuth 2.0 Authorization server introspection endpoint."),
3062 		AP_INIT_TAKE1(OIDCOAuthIntrospectionEndpointKey,
3063 				oidc_set_string_slot,
3064 				(void*)APR_OFFSETOF(oidc_cfg, oauth.introspection_endpoint_tls_client_key),
3065 				RSRC_CONF,
3066 				"TLS client certificate private key used for calls to the OAuth 2.0 Authorization server introspection endpoint."),
3067 
3068 		AP_INIT_TAKE1(OIDCOAuthIntrospectionTokenParamName,
3069 				oidc_set_string_slot,
3070 				(void*)APR_OFFSETOF(oidc_cfg, oauth.introspection_token_param_name),
3071 				RSRC_CONF,
3072 				"Name of the parameter whose value carries the access token value in an validation request to the token introspection endpoint."),
3073 		AP_INIT_TAKE123(OIDCOAuthTokenExpiryClaim,
3074 				oidc_set_token_expiry_claim,
3075 				NULL,
3076 				RSRC_CONF,
3077 				"Name of the claim that carries the token expiry value in the introspection result, optionally followed by absolute|relative, optionally followed by optional|mandatory"),
3078 		AP_INIT_TAKE1(OIDCOAuthSSLValidateServer,
3079 				oidc_set_ssl_validate_slot,
3080 				(void*)APR_OFFSETOF(oidc_cfg, oauth.ssl_validate_server),
3081 				RSRC_CONF,
3082 				"Require validation of the OAuth 2.0 AS Validation Endpoint SSL server certificate for successful authentication (On or Off)"),
3083 		AP_INIT_TAKE123(OIDCOAuthRemoteUserClaim,
3084 				oidc_set_remote_user_claim,
3085 				(void*)APR_OFFSETOF(oidc_cfg, oauth.remote_user_claim),
3086 				RSRC_CONF,
3087 				"The claim that is used when setting the REMOTE_USER variable for OAuth 2.0 protected paths."),
3088 		AP_INIT_ITERATE(OIDCOAuthVerifyCertFiles,
3089 				oidc_set_public_key_files,
3090 				(void*)APR_OFFSETOF(oidc_cfg, oauth.verify_public_keys),
3091 				RSRC_CONF,
3092 				"The fully qualified names of the files that contain the X.509 certificates that contains the RSA public keys that can be used for access token validation."),
3093 		AP_INIT_ITERATE(OIDCOAuthVerifySharedKeys,
3094 				oidc_set_shared_keys,
3095 				(void*)APR_OFFSETOF(oidc_cfg, oauth.verify_shared_keys),
3096 				RSRC_CONF,
3097 				"Shared secret(s) that is/are used to verify signed JWT access tokens locally."),
3098 		AP_INIT_TAKE1(OIDCOAuthVerifyJwksUri,
3099 				oidc_set_https_slot,
3100 				(void *)APR_OFFSETOF(oidc_cfg, oauth.verify_jwks_uri),
3101 				RSRC_CONF,
3102 				"The JWKs URL on which the Authorization publishes the keys used to sign its JWT access tokens."),
3103 
3104 		AP_INIT_TAKE1(OIDCHTTPTimeoutLong,
3105 				oidc_set_int_slot,
3106 				(void*)APR_OFFSETOF(oidc_cfg, http_timeout_long),
3107 				RSRC_CONF,
3108 				"Timeout for long duration HTTP calls (default)."),
3109 		AP_INIT_TAKE1(OIDCHTTPTimeoutShort,
3110 				oidc_set_int_slot,
3111 				(void*)APR_OFFSETOF(oidc_cfg, http_timeout_short),
3112 				RSRC_CONF,
3113 				"Timeout for short duration HTTP calls (registry/discovery)."),
3114 		AP_INIT_TAKE1(OIDCStateTimeout,
3115 				oidc_set_int_slot,
3116 				(void*)APR_OFFSETOF(oidc_cfg, state_timeout),
3117 				RSRC_CONF,
3118 				"Time to live in seconds for state parameter (cq. interval in which the authorization request and the corresponding response need to be completed)."),
3119 		AP_INIT_TAKE12(OIDCStateMaxNumberOfCookies,
3120 				oidc_set_max_number_of_state_cookies,
3121 				(void*)APR_OFFSETOF(oidc_cfg, max_number_of_state_cookies),
3122 				RSRC_CONF,
3123 				"Maximun number of parallel state cookies i.e. outstanding authorization requests and whether to delete the oldest cookie(s)."),
3124 		AP_INIT_TAKE1(OIDCSessionInactivityTimeout,
3125 				oidc_set_session_inactivity_timeout,
3126 				(void*)APR_OFFSETOF(oidc_cfg, session_inactivity_timeout),
3127 				RSRC_CONF,
3128 				"Inactivity interval after which the session is invalidated when no interaction has occurred."),
3129 
3130 		AP_INIT_TAKE1(OIDCMetadataDir,
3131 				oidc_set_dir_slot,
3132 				(void*)APR_OFFSETOF(oidc_cfg, metadata_dir),
3133 				RSRC_CONF,
3134 				"Directory that contains provider and client metadata files."),
3135 		AP_INIT_TAKE1(OIDCSessionType,
3136 				oidc_set_session_type,
3137 				(void*)APR_OFFSETOF(oidc_cfg, session_type),
3138 				RSRC_CONF,
3139 				"OpenID Connect session storage type (Apache 2.0/2.2 only). Must be one of \"server-cache\" or \"client-cookie\" with an optional suffix \":persistent\"."),
3140 		AP_INIT_FLAG(OIDCSessionCacheFallbackToCookie,
3141 				oidc_set_flag_slot,
3142 				(void*)APR_OFFSETOF(oidc_cfg, session_cache_fallback_to_cookie),
3143 				RSRC_CONF,
3144 				"Fallback to client-side cookie session storage when server side cache fails."),
3145 		AP_INIT_TAKE1(OIDCSessionCookieChunkSize,
3146 				oidc_set_int_slot,
3147 				(void*)APR_OFFSETOF(oidc_cfg, session_cookie_chunk_size),
3148 				RSRC_CONF,
3149 				"Chunk size for client-cookie session storage type in bytes. Defaults to 4k. Set 0 to suppress chunking."),
3150 
3151 		AP_INIT_TAKE1(OIDCCacheType,
3152 				oidc_set_cache_type,
3153 				(void*)APR_OFFSETOF(oidc_cfg, cache), RSRC_CONF,
3154 				"Cache type; must be one of \"file\", \"memcache\" or \"shm\"."),
3155 		AP_INIT_FLAG(OIDCCacheEncrypt,
3156 				oidc_set_flag_slot,
3157 				(void*)APR_OFFSETOF(oidc_cfg, cache_encrypt),
3158 				RSRC_CONF,
3159 				"Encrypt the data in the cache backend (On or Off)"),
3160 		AP_INIT_TAKE1(OIDCCacheDir,
3161 				oidc_set_dir_slot,
3162 				(void*)APR_OFFSETOF(oidc_cfg, cache_file_dir),
3163 				RSRC_CONF,
3164 				"Directory used for file-based caching."),
3165 		AP_INIT_TAKE1(OIDCCacheFileCleanInterval,
3166 				oidc_set_int_slot,
3167 				(void*)APR_OFFSETOF(oidc_cfg, cache_file_clean_interval),
3168 				RSRC_CONF,
3169 				"Cache file clean interval in seconds."),
3170 #ifdef USE_MEMCACHE
3171 		AP_INIT_TAKE1(OIDCMemCacheServers,
3172 				oidc_set_string_slot,
3173 				(void*)APR_OFFSETOF(oidc_cfg, cache_memcache_servers),
3174 				RSRC_CONF,
3175 				"Memcache servers used for caching (space separated list of <hostname>[:<port>] tuples)"),
3176 #endif
3177 		AP_INIT_TAKE1(OIDCCacheShmMax,
3178 				oidc_set_int_slot,
3179 				(void*)APR_OFFSETOF(oidc_cfg, cache_shm_size_max),
3180 				RSRC_CONF,
3181 				"Maximum number of cache entries to use for \"shm\" caching."),
3182 		AP_INIT_TAKE1(OIDCCacheShmEntrySizeMax,
3183 				oidc_set_cache_shm_entry_size_max,
3184 				(void*)APR_OFFSETOF(oidc_cfg, cache_shm_entry_size_max),
3185 				RSRC_CONF,
3186 				"Maximum size of a single cache entry used for \"shm\" caching."),
3187 #ifdef USE_LIBHIREDIS
3188 		AP_INIT_TAKE1(OIDCRedisCacheServer,
3189 				oidc_set_string_slot,
3190 				(void*)APR_OFFSETOF(oidc_cfg, cache_redis_server),
3191 				RSRC_CONF,
3192 				"Redis server used for caching (<hostname>[:<port>])"),
3193 		AP_INIT_TAKE1(OIDCRedisCachePassword,
3194 				oidc_set_string_slot,
3195 				(void*)APR_OFFSETOF(oidc_cfg, cache_redis_password),
3196 				RSRC_CONF,
3197 				"Password for authentication to the Redis servers."),
3198 		AP_INIT_TAKE1(OIDCRedisCacheDatabase,
3199 				oidc_set_int_slot,
3200 				(void*)APR_OFFSETOF(oidc_cfg, cache_redis_database),
3201 				RSRC_CONF,
3202 				"Database for the Redis servers."),
3203 #endif
3204 		AP_INIT_TAKE1(OIDCHTMLErrorTemplate,
3205 				oidc_set_string_slot,
3206 				(void*)APR_OFFSETOF(oidc_cfg, error_template),
3207 				RSRC_CONF,
3208 				"Name of a HTML error template: needs to contain two \"%s\" characters, one for the error message, one for the description."),
3209 
3210 		AP_INIT_TAKE1(OIDCDiscoverURL,
3211 				oidc_set_relative_or_absolute_url_slot_dir_cfg,
3212 				(void *)APR_OFFSETOF(oidc_dir_cfg, discover_url),
3213 				RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
3214 				"Defines an external IDP Discovery page"),
3215 		AP_INIT_ITERATE(OIDCPassCookies,
3216 				oidc_set_cookie_names,
3217 				(void *) APR_OFFSETOF(oidc_dir_cfg, pass_cookies),
3218 				RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
3219 				"Specify cookies that need to be passed from the browser on to the backend to the OP/AS."),
3220 		AP_INIT_ITERATE(OIDCStripCookies,
3221 				oidc_set_cookie_names,
3222 				(void *) APR_OFFSETOF(oidc_dir_cfg, strip_cookies),
3223 				RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
3224 				"Specify cookies that should be stripped from the incoming request before passing it on to the backend."),
3225 		AP_INIT_TAKE1(OIDCAuthNHeader,
3226 				ap_set_string_slot,
3227 				(void *) APR_OFFSETOF(oidc_dir_cfg, authn_header),
3228 				RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
3229 				"Specify the HTTP header variable to set with the name of the authenticated user. By default no explicit header is added but Apache's default REMOTE_USER will be set."),
3230 		AP_INIT_TAKE1(OIDCCookiePath,
3231 				ap_set_string_slot,
3232 				(void *) APR_OFFSETOF(oidc_dir_cfg, cookie_path),
3233 				RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
3234 				"Define the cookie path for the session cookie."),
3235 		AP_INIT_TAKE1(OIDCCookie,
3236 				ap_set_string_slot,
3237 				(void *) APR_OFFSETOF(oidc_dir_cfg, cookie),
3238 				RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
3239 				"Define the cookie name for the session cookie."),
3240 		AP_INIT_TAKE12(OIDCUnAuthAction,
3241 				oidc_set_unauth_action,
3242 				(void *) APR_OFFSETOF(oidc_dir_cfg, unauth_action),
3243 				RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
3244 				"Sets the action taken when an unauthenticated request occurs: must be one of \"auth\" (default), \"pass\" , \"401\", \"407\", or \"410\"."),
3245 		AP_INIT_TAKE1(OIDCUnAutzAction,
3246 				oidc_set_unautz_action,
3247 				(void *) APR_OFFSETOF(oidc_dir_cfg, unautz_action),
3248 				RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
3249 				"Sets the action taken when an unauthorized request occurs: must be one of \"401\" (default), \"403\" or \"auth\"."),
3250 		AP_INIT_TAKE12(OIDCPassClaimsAs,
3251 				oidc_set_pass_claims_as, NULL,
3252 				RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
3253 				"Specify how claims are passed to the application(s); must be one of \"none\", \"headers\", \"environment\" or \"both\" (default)."),
3254 		AP_INIT_ITERATE(OIDCOAuthAcceptTokenAs,
3255 				oidc_set_accept_oauth_token_in,
3256 				NULL,
3257 				RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
3258 				"The method in which an OAuth token can be presented; must be one or more of: header|post|query|cookie"),
3259 		AP_INIT_TAKE1(OIDCUserInfoRefreshInterval,
3260 				oidc_set_userinfo_refresh_interval,
3261 				(void*)APR_OFFSETOF(oidc_cfg, provider.userinfo_refresh_interval),
3262 				RSRC_CONF,
3263 				"Duration in seconds after which retrieved claims from the userinfo endpoint should be refreshed."),
3264 		AP_INIT_TAKE1(OIDCOAuthTokenIntrospectionInterval,
3265 				ap_set_int_slot,
3266 				(void *) APR_OFFSETOF(oidc_dir_cfg, oauth_token_introspect_interval),
3267 				RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
3268 				"Sets the token introspection refresh interval."),
3269 		AP_INIT_TAKE1(OIDCPreservePost,
3270 				oidc_set_preserve_post,
3271 				(void *) APR_OFFSETOF(oidc_dir_cfg, preserve_post),
3272 				RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
3273 				"Indicates whether POST parameters will be preserved across authentication requests."),
3274 		AP_INIT_FLAG(OIDCPassRefreshToken,
3275 				ap_set_flag_slot,
3276 				(void*)APR_OFFSETOF(oidc_dir_cfg, pass_refresh_token),
3277 				RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
3278 				"Pass the refresh token in a header and/or environment variable (On or Off)"),
3279 		AP_INIT_TAKE1(OIDCRequestObject,
3280 				oidc_set_string_slot,
3281 				(void *)APR_OFFSETOF(oidc_cfg, provider.request_object),
3282 				RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
3283 				"The default request object settings"),
3284 		AP_INIT_TAKE1(OIDCProviderMetadataRefreshInterval,
3285 				oidc_set_int_slot,
3286 				(void*)APR_OFFSETOF(oidc_cfg, provider_metadata_refresh_interval),
3287 				RSRC_CONF,
3288 				"Provider metadata refresh interval in seconds."),
3289 		AP_INIT_TAKE1(OIDCProviderAuthRequestMethod,
3290 				oidc_set_auth_request_method,
3291 				(void*)APR_OFFSETOF(oidc_cfg, provider.auth_request_method),
3292 				RSRC_CONF,
3293 				"HTTP method used to send the authentication request to the provider (GET or POST)."),
3294 		AP_INIT_ITERATE(OIDCInfoHook,
3295 				oidc_set_info_hook_data,
3296 				(void *)APR_OFFSETOF(oidc_cfg, info_hook_data),
3297 				RSRC_CONF,
3298 				"The data that will be returned from the info hook."),
3299 		AP_INIT_ITERATE(OIDCBlackListedClaims,
3300 				oidc_set_filtered_claims,
3301 				(void *) APR_OFFSETOF(oidc_cfg, black_listed_claims),
3302 				RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
3303 				"Specify claims that should be removed from the userinfo and/or id_token before storing them in the session."),
3304 		AP_INIT_ITERATE(OIDCWhiteListedClaims,
3305 				oidc_set_filtered_claims,
3306 				(void *) APR_OFFSETOF(oidc_cfg, white_listed_claims),
3307 				RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
3308 				"Specify claims from the userinfo and/or id_token that should be stored in the session (all other claims will be discarded)."),
3309 		AP_INIT_TAKE1(OIDCOAuthServerMetadataURL,
3310 				oidc_set_url_slot,
3311 				(void*)APR_OFFSETOF(oidc_cfg, oauth.metadata_url),
3312 				RSRC_CONF,
3313 				"Authorization Server metadata URL."),
3314 		AP_INIT_TAKE1(OIDCOAuthAccessTokenBindingPolicy,
3315 				oidc_set_token_binding_policy,
3316 				(void *)APR_OFFSETOF(oidc_cfg, oauth.access_token_binding_policy),
3317 				RSRC_CONF,
3318 				"The token binding policy used for access tokens; must be one of [disabled|optional|required|enforced]"),
3319 
3320 		AP_INIT_TAKE12(OIDCRefreshAccessTokenBeforeExpiry,
3321 				oidc_set_refresh_access_token_before_expiry,
3322 				(void *)APR_OFFSETOF(oidc_dir_cfg, refresh_access_token_before_expiry),
3323 				RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
3324 				"Ensure the access token is valid for at least <x> seconds by refreshing it if required; must be: <x> [logout_on_error]; the logout_on_error performs a logout on refresh error."),
3325 
3326 		AP_INIT_TAKE1(OIDCStateInputHeaders,
3327 				oidc_set_state_input_headers_as,
3328 				NULL,
3329 				RSRC_CONF,
3330 				"Specify header name which is used as the input for calculating the fingerprint of the state during authentication; must be one of \"none\", \"user-agent\", \"x-forwarded-for\" or \"both\" (default)."),
3331 
3332 		AP_INIT_ITERATE(OIDCRedirectURLsAllowed,
3333 				oidc_set_redirect_urls_allowed,
3334 				(void *) APR_OFFSETOF(oidc_cfg, redirect_urls_allowed),
3335 				RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
3336 				"Specify one or more regular expressions that define URLs allowed for post logout and other redirects."),
3337 
3338 		AP_INIT_TAKE1(OIDCStateCookiePrefix,
3339 				ap_set_string_slot,
3340 				(void *) APR_OFFSETOF(oidc_dir_cfg, state_cookie_prefix),
3341 				RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
3342 				"Define the cookie prefix for the state cookie."),
3343 
3344 		AP_INIT_TAKE1(OIDCCABundlePath,
3345 				oidc_set_path_slot,
3346 				(void *) APR_OFFSETOF(oidc_cfg, ca_bundle_path),
3347 				RSRC_CONF,
3348 				"Sets the path to the CA bundle to be used by cURL."),
3349 
3350 		{ NULL }
3351 };
3352