Hello community,

here is the log from the commit of package apache2-mod_auth_openidc for 
openSUSE:Factory checked in at 2020-08-12 10:28:26
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/apache2-mod_auth_openidc (Old)
 and      /work/SRC/openSUSE:Factory/.apache2-mod_auth_openidc.new.3399 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "apache2-mod_auth_openidc"

Wed Aug 12 10:28:26 2020 rev:10 rq:825751 version:2.4.3

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/apache2-mod_auth_openidc/apache2-mod_auth_openidc.changes
        2020-03-25 23:49:02.792040419 +0100
+++ 
/work/SRC/openSUSE:Factory/.apache2-mod_auth_openidc.new.3399/apache2-mod_auth_openidc.changes
      2020-08-12 10:29:52.412028787 +0200
@@ -1,0 +2,17 @@
+Tue Aug 11 08:20:49 UTC 2020 - Michael Ströder <[email protected]>
+
+- Update to version 2.4.3
+  * Bugfixes
+    - prevent open redirect on refresh token requests
+    - add new OIDCRedirectURLsAllowed primitive to handle post logout
+      and refresh-return-to validation
+      addresses #453; closes #466
+    - when stripping cookies, add a space between cookies in the resulting 
header (required by RFC 6265)
+    - fix compilation against Apache 2.0
+  * Features
+    - add OIDCStateInputHeaders that allows configuring the header values 
+      used to calculate the fingerprint of the state during authentication
+    - added OIDCValidateIssuer primitive to allow for disabling of issuer 
+      matching, helps to support multi-tenant applications i.e. Microsoft AAD
+
+-------------------------------------------------------------------

Old:
----
  apache2-mod_auth_openidc-2.4.2.1.tar.gz

New:
----
  apache2-mod_auth_openidc-2.4.3.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ apache2-mod_auth_openidc.spec ++++++
--- /var/tmp/diff_new_pack.QO0WBj/_old  2020-08-12 10:29:54.040030044 +0200
+++ /var/tmp/diff_new_pack.QO0WBj/_new  2020-08-12 10:29:54.040030044 +0200
@@ -19,7 +19,7 @@
 %define apxs %{_sbindir}/apxs2
 %define apache_libexecdir %(%{apxs} -q LIBEXECDIR)
 Name:           apache2-mod_auth_openidc
-Version:        2.4.2.1
+Version:        2.4.3
 Release:        0
 Summary:        Apache2.x module for an OpenID Connect enabled Identity 
Provider
 License:        Apache-2.0

++++++ apache2-mod_auth_openidc-2.4.2.1.tar.gz -> 
apache2-mod_auth_openidc-2.4.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mod_auth_openidc-2.4.2.1/AUTHORS 
new/mod_auth_openidc-2.4.3/AUTHORS
--- old/mod_auth_openidc-2.4.2.1/AUTHORS        2020-03-25 13:09:26.000000000 
+0100
+++ new/mod_auth_openidc-2.4.3/AUTHORS  2020-06-10 18:14:24.000000000 +0200
@@ -61,3 +61,4 @@
        Paolo Battino
        absynth76 <https://github.com/absynth76>
        Aaron Jones <https://github.com/wwaaron>
+       Bryan Ingram <https://github/bcingram>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mod_auth_openidc-2.4.2.1/ChangeLog 
new/mod_auth_openidc-2.4.3/ChangeLog
--- old/mod_auth_openidc-2.4.2.1/ChangeLog      2020-03-25 13:09:26.000000000 
+0100
+++ new/mod_auth_openidc-2.4.3/ChangeLog        2020-06-10 18:14:24.000000000 
+0200
@@ -1,3 +1,26 @@
+06/10/2020
+- prevent open redirect on refresh token requests
+  add new OIDCRedirectURLsAllowed primitive to handle post logout and 
refresh-return-to validation
+  addresses #453; closes #466
+- release 2.4.3
+
+06/09/2020
+- fix complex expressions crash when compiled from source with libjq; closes 
#472
+  thanks vincentscharf0803
+  introduced by OIDCStateInputHeaders addition in 2.4.3rc0
+- bump to 2.4.3rc1
+
+05/11/2020
+- added OIDCValidateIssuer to allow for disabling of issuer matching.  helps 
to support multi-tenant applications.
+
+05/02/2020
+- when stripping cookies, add a space between cookies in the resulting header 
(required by RFC 6265)
+- move oidc_parse_config inside MODULE_MAGIC_NUMBER_MAJOR to make sure the 
module compiles with Apache 2.0
+
+04/25/2020
+- add OIDCStateInputHeaders that allows configuring the header values used to 
calculate the fingerprint of the state during authentication
+- bump to 2.4.3rc0
+
 03/25/2020
 - oops: fix json_deep_copy of claims
 - release 2.4.2.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mod_auth_openidc-2.4.2.1/auth_openidc.conf 
new/mod_auth_openidc-2.4.3/auth_openidc.conf
--- old/mod_auth_openidc-2.4.2.1/auth_openidc.conf      2020-03-25 
13:09:26.000000000 +0100
+++ new/mod_auth_openidc-2.4.3/auth_openidc.conf        2020-06-10 
18:14:24.000000000 +0200
@@ -137,6 +137,11 @@
 # NB: this can be overridden on a per-OP basis in the .conf file using the 
key: ssl_validate_server
 #OIDCSSLValidateServer [On|Off]
 
+# Require configured issuer to match the issuer returned in id_token.
+# (Disable to support Azure AD multi-tenant applications.)
+# When not defined, the default value is "On".
+#OIDCValidateIssuer [On|Off]
+
 # The refresh interval in seconds for the claims obtained from the userinfo 
endpoint
 # When not defined the default is 0, i.e. the claims are retrieved only at 
session creation time.
 # NB: this can be overridden on a per-OP basis in the .conf file using the 
key: userinfo_refresh_interval
@@ -823,3 +828,17 @@
 # When not defined no attempt is made to refresh the access token (unless 
implicitly with OIDCUserInfoRefreshInterval)
 # The optional logout_on_error flag makes the refresh logout the current local 
session if the refresh fails.
 #OIDCRefreshAccessTokenBeforeExpiry <seconds> [logout_on_error]
+
+# Defines whether the value of the User-Agent and X-Forwarded-For headers will 
be used as the input
+# for calculating the fingerprint of the state during authentication.
+# When not defined the default "both" is used.
+#OIDCStateInputHeaders [none|user-agent|x-forwarded-for|both]
+
+# Define one or more regular expressions that specify URLs (or domains) 
allowed for post logout and
+# other redirects such as the "return_to" value on refresh token requests, 
e.g.:
+#   OIDCRedirectURLsAllowed ^https://www.example.com 
^https://(\w+).example.org ^https://example.net/app
+# or:
+#   OIDCRedirectURLsAllowed ^https://www.example.com/logout$ 
^https://www.example.com/app/return_to$ 
+# When not defined, the default is to match the hostname in the URL redirected 
to against
+# the hostname in the current request.
+#OIDCRedirectURLsAllowed [<regexp>]+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mod_auth_openidc-2.4.2.1/configure.ac 
new/mod_auth_openidc-2.4.3/configure.ac
--- old/mod_auth_openidc-2.4.2.1/configure.ac   2020-03-25 13:09:26.000000000 
+0100
+++ new/mod_auth_openidc-2.4.3/configure.ac     2020-06-10 18:14:24.000000000 
+0200
@@ -1,4 +1,4 @@
-AC_INIT([mod_auth_openidc],[2.4.2.1],[[email protected]])
+AC_INIT([mod_auth_openidc],[2.4.3],[[email protected]])
 
 AC_SUBST(NAMEVER, AC_PACKAGE_TARNAME()-AC_PACKAGE_VERSION())
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mod_auth_openidc-2.4.2.1/src/authz.c 
new/mod_auth_openidc-2.4.3/src/authz.c
--- old/mod_auth_openidc-2.4.2.1/src/authz.c    2020-03-25 13:09:26.000000000 
+0100
+++ new/mod_auth_openidc-2.4.3/src/authz.c      2020-06-10 18:14:24.000000000 
+0200
@@ -436,10 +436,14 @@
        if (!claims)
                return AUTHZ_DENIED;
 
-       t = ap_expr_str_exec(r, expr, &err);
-       if (err) {
-               oidc_error(r, "could not evaluate expression '%s': %s", 
require_args, err);
-               return AUTHZ_DENIED;
+       if (expr) {
+               t = ap_expr_str_exec(r, expr, &err);
+               if (err) {
+                       oidc_error(r, "could not evaluate expression '%s': %s", 
require_args, err);
+                       return AUTHZ_DENIED;
+               }
+       } else {
+               t = require_args;
        }
 
        /* loop over the Required specifications */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mod_auth_openidc-2.4.2.1/src/config.c 
new/mod_auth_openidc-2.4.3/src/config.c
--- old/mod_auth_openidc-2.4.2.1/src/config.c   2020-03-25 13:09:26.000000000 
+0100
+++ new/mod_auth_openidc-2.4.3/src/config.c     2020-06-10 18:14:24.000000000 
+0200
@@ -76,6 +76,8 @@
 
 /* validate SSL server certificates by default */
 #define OIDC_DEFAULT_SSL_VALIDATE_SERVER 1
+/* validate issuer by default */
+#define OIDC_DEFAULT_VALIDATE_ISSUER 1
 /* default scope requested from the OP */
 #define OIDC_DEFAULT_SCOPE "openid"
 /* default claim delimiter for multi-valued claims passed in a HTTP header */
@@ -168,6 +170,8 @@
 #define OIDC_DEFAULT_PROVIDER_ISSUER_SPECIFIC_REDIRECT_URI 0
 /* define the default number of seconds that the access token needs to be 
valid for; -1 = no refresh */
 #define OIDC_DEFAULT_REFRESH_ACCESS_TOKEN_BEFORE_EXPIRY -1
+/* default setting for calculating the fingerprint of the state from request 
headers during authentication */
+#define OIDC_DEFAULT_STATE_INPUT_HEADERS (OIDC_STATE_INPUT_HEADERS_USER_AGENT 
| OIDC_STATE_INPUT_HEADERS_X_FORWARDED_FOR)
 
 #define OIDCProviderMetadataURL                "OIDCProviderMetadataURL"
 #define OIDCProviderIssuer                     "OIDCProviderIssuer"
@@ -195,6 +199,7 @@
 #define OIDCUserInfoTokenMethod                "OIDCUserInfoTokenMethod"
 #define OIDCTokenBindingPolicy                 "OIDCTokenBindingPolicy"
 #define OIDCSSLValidateServer                  "OIDCSSLValidateServer"
+#define OIDCValidateIssuer                     "OIDCValidateIssuer"
 #define OIDCClientName                         "OIDCClientName"
 #define OIDCClientContact                      "OIDCClientContact"
 #define OIDCScope                              "OIDCScope"
@@ -267,6 +272,8 @@
 #define OIDCOAuthServerMetadataURL             "OIDCOAuthServerMetadataURL"
 #define OIDCOAuthAccessTokenBindingPolicy      
"OIDCOAuthAccessTokenBindingPolicy"
 #define OIDCRefreshAccessTokenBeforeExpiry     
"OIDCRefreshAccessTokenBeforeExpiry"
+#define OIDCStateInputHeaders                  "OIDCStateInputHeaders"
+#define OIDCRedirectURLsAllowed                "OIDCRedirectURLsAllowed"
 
 extern module AP_MODULE_DECLARE_DATA auth_openidc_module;
 
@@ -466,6 +473,20 @@
 }
 
 /*
+ * set validate issuer slot
+ */
+static const char *oidc_set_validate_issuer_slot(cmd_parms *cmd,
+               void *struct_ptr, const char *arg) {
+       oidc_cfg *cfg = (oidc_cfg *) ap_get_module_config(
+                       cmd->server->module_config, &auth_openidc_module);
+       int b = 0;
+       const char *rv = oidc_parse_boolean(cmd->pool, arg, &b);
+       if (rv == NULL)
+               rv = ap_set_flag_slot(cmd, cfg, b);
+       return OIDC_CONFIG_DIR_RV(cmd, rv);
+}
+
+/*
  * return the right token endpoint authentication method validation function, 
based on whether private keys are set
  */
 oidc_valid_function_t oidc_cfg_get_valid_endpoint_auth_function(oidc_cfg *cfg) 
{
@@ -1082,17 +1103,40 @@
        const char *rv1 = 
oidc_parse_refresh_access_token_before_expiry(cmd->pool,
                        arg1, &dir_cfg->refresh_access_token_before_expiry);
        if (rv1 != NULL)
-               return apr_psprintf(cmd->pool, "Invalid value for directive 
'%s': %s", cmd->directive->directive, rv1);
+               return apr_psprintf(cmd->pool, "Invalid value for directive 
'%s': %s",
+                               cmd->directive->directive, rv1);
 
        if (arg2) {
-               const char *rv2 = 
oidc_parse_logout_on_error_refresh_as(cmd->pool,
-                       arg2, &dir_cfg->logout_on_error_refresh);
+               const char *rv2 = 
oidc_parse_logout_on_error_refresh_as(cmd->pool, arg2,
+                               &dir_cfg->logout_on_error_refresh);
                return OIDC_CONFIG_DIR_RV(cmd, rv2);
        }
 
        return NULL;
 }
 
+/*
+ * define which header we use for calculating the fingerprint of the state 
during authentication
+ */
+static const char * oidc_set_state_input_headers_as(cmd_parms *cmd, void *m,
+               const char *arg) {
+       oidc_cfg *cfg = (oidc_cfg *) ap_get_module_config(
+                       cmd->server->module_config, &auth_openidc_module);
+       const char *rv = oidc_parse_set_state_input_headers_as(cmd->pool, arg,
+                       &cfg->state_input_headers);
+       return OIDC_CONFIG_DIR_RV(cmd, rv);
+}
+
+static const char * oidc_set_redirect_urls_allowed(cmd_parms *cmd, void *m,
+               const char *arg) {
+       oidc_cfg *cfg = (oidc_cfg *) ap_get_module_config(
+                       cmd->server->module_config, &auth_openidc_module);
+       if (cfg->redirect_urls_allowed == NULL)
+               cfg->redirect_urls_allowed = apr_hash_make(cmd->pool);
+       apr_hash_set(cfg->redirect_urls_allowed, arg, APR_HASH_KEY_STRING, arg);
+       return NULL;
+}
+
 int oidc_cfg_dir_refresh_access_token_before_expiry(request_rec *r) {
        oidc_dir_cfg *dir_cfg = ap_get_module_config(r->per_dir_config,
                        &auth_openidc_module);
@@ -1130,6 +1174,7 @@
        provider->backchannel_logout_supported = OIDC_CONFIG_POS_INT_UNSET;
 
        provider->ssl_validate_server = OIDC_DEFAULT_SSL_VALIDATE_SERVER;
+       provider->validate_issuer = OIDC_DEFAULT_VALIDATE_ISSUER;
        provider->client_name = OIDC_DEFAULT_CLIENT_NAME;
        provider->client_contact = NULL;
        provider->registration_token = NULL;
@@ -1268,6 +1313,10 @@
        c->provider.issuer_specific_redirect_uri =
                        OIDC_DEFAULT_PROVIDER_ISSUER_SPECIFIC_REDIRECT_URI;
 
+       c->state_input_headers = OIDC_DEFAULT_STATE_INPUT_HEADERS;
+
+       c->redirect_urls_allowed = NULL;
+
        return c;
 }
 
@@ -1371,6 +1420,10 @@
                        != OIDC_DEFAULT_SSL_VALIDATE_SERVER ?
                                        add->provider.ssl_validate_server :
                                        base->provider.ssl_validate_server;
+       c->provider.validate_issuer =
+                       add->provider.validate_issuer != 
OIDC_DEFAULT_VALIDATE_ISSUER ?
+                                       add->provider.validate_issuer :
+                                       base->provider.validate_issuer;
        c->provider.client_name =
                        apr_strnatcmp(add->provider.client_name, 
OIDC_DEFAULT_CLIENT_NAME)
                        != 0 ?
@@ -1731,6 +1784,14 @@
                                        
add->provider.issuer_specific_redirect_uri :
                                        
base->provider.issuer_specific_redirect_uri;
 
+       c->state_input_headers =
+                       add->state_input_headers != 
OIDC_DEFAULT_STATE_INPUT_HEADERS ?
+                                       add->state_input_headers : 
base->state_input_headers;
+
+       c->redirect_urls_allowed =
+                       add->redirect_urls_allowed != NULL ?
+                                       add->redirect_urls_allowed : 
base->redirect_urls_allowed;
+
        return c;
 }
 
@@ -2359,29 +2420,26 @@
        return oidc_config_check_merged_vhost_configs(pool, s);
 }
 
+#if MODULE_MAGIC_NUMBER_MAJOR >= 20100714
 static const char *oidc_parse_config(cmd_parms *cmd, const char *require_line,
                const void **parsed_require_line) {
        const char *expr_err = NULL;
        ap_expr_info_t *expr;
 
        expr = ap_expr_parse_cmd(cmd, require_line, AP_EXPR_FLAG_STRING_RESULT,
-               &expr_err, NULL);
+                       &expr_err, NULL);
 
        if (expr_err)
                return apr_pstrcat(cmd->temp_pool,
-                       "Cannot parse expression in require line: ",
-                       expr_err, NULL);
+                               "Cannot parse expression in require line: ", 
expr_err, NULL);
 
        *parsed_require_line = expr;
 
        return NULL;
 }
 
-#if MODULE_MAGIC_NUMBER_MAJOR >= 20100714
 static const authz_provider oidc_authz_claim_provider = {
-               &oidc_authz_checker_claim,
-               &oidc_parse_config,
-};
+               &oidc_authz_checker_claim, &oidc_parse_config, };
 #ifdef USE_LIBJQ
 static const authz_provider oidc_authz_claims_expr_provider = {
                &oidc_authz_checker_claims_expr,
@@ -2671,6 +2729,11 @@
                                (void*)APR_OFFSETOF(oidc_cfg, 
provider.ssl_validate_server),
                                RSRC_CONF,
                                "Require validation of the OpenID Connect OP 
SSL server certificate for successful authentication (On or Off)"),
+               AP_INIT_TAKE1(OIDCValidateIssuer,
+                               oidc_set_validate_issuer_slot,
+                               (void*)APR_OFFSETOF(oidc_cfg, 
provider.validate_issuer),
+                               RSRC_CONF,
+                               "Require validation of token issuer for 
successful authentication  (On or Off)"),
                AP_INIT_TAKE1(OIDCClientName,
                                oidc_set_string_slot,
                                (void *) APR_OFFSETOF(oidc_cfg, 
provider.client_name),
@@ -3111,5 +3174,17 @@
                                RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
                                "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."),
 
+               AP_INIT_TAKE1(OIDCStateInputHeaders,
+                               oidc_set_state_input_headers_as,
+                               NULL,
+                               RSRC_CONF,
+                               "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)."),
+
+               AP_INIT_ITERATE(OIDCRedirectURLsAllowed,
+                               oidc_set_redirect_urls_allowed,
+                               (void *) APR_OFFSETOF(oidc_cfg, 
redirect_urls_allowed),
+                               RSRC_CONF|ACCESS_CONF|OR_AUTHCFG,
+                               "Specify one or more regular expressions that 
define URLs allowed for post logout and other redirects."),
+
                { NULL }
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mod_auth_openidc-2.4.2.1/src/jose.h 
new/mod_auth_openidc-2.4.3/src/jose.h
--- old/mod_auth_openidc-2.4.2.1/src/jose.h     2020-03-25 13:09:26.000000000 
+0100
+++ new/mod_auth_openidc-2.4.3/src/jose.h       2020-06-10 18:14:24.000000000 
+0200
@@ -153,7 +153,7 @@
        int kty;
        /* key identifier */
        char *kid;
-       /* X.509 Certificate Chain */;
+       /* X.509 Certificate Chain */
        unsigned char **x5c;
        /* the size of the certificate chain */
        int x5c_count;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mod_auth_openidc-2.4.2.1/src/metadata.c 
new/mod_auth_openidc-2.4.3/src/metadata.c
--- old/mod_auth_openidc-2.4.2.1/src/metadata.c 2020-03-25 13:09:26.000000000 
+0100
+++ new/mod_auth_openidc-2.4.3/src/metadata.c   2020-06-10 18:14:24.000000000 
+0200
@@ -109,6 +109,7 @@
 #define OIDC_METADATA_POST_LOGOUT_REDIRECT_URIS                    
"post_logout_redirect_uris"
 #define OIDC_METADATA_IDTOKEN_BINDING_CNF                          
"id_token_token_binding_cnf"
 #define OIDC_METADATA_SSL_VALIDATE_SERVER                          
"ssl_validate_server"
+#define OIDC_METADATA_VALIDATE_ISSUER                              
"validate_issuer"
 #define OIDC_METADATA_SCOPE                                        "scope"
 #define OIDC_METADATA_JWKS_REFRESH_INTERVAL                        
"jwks_refresh_interval"
 #define OIDC_METADATA_IDTOKEN_IAT_SLACK                            
"idtoken_iat_slack"
@@ -1235,6 +1236,9 @@
        oidc_metadata_parse_boolean(r, j_conf, 
OIDC_METADATA_SSL_VALIDATE_SERVER,
                        &provider->ssl_validate_server, 
cfg->provider.ssl_validate_server);
 
+       oidc_metadata_parse_boolean(r, j_conf, OIDC_METADATA_VALIDATE_ISSUER,
+                       &provider->validate_issuer, 
cfg->provider.validate_issuer);
+
        /* find out what scopes we should be requesting from this provider */
        // TODO: use the provider "scopes_supported" to mix-and-match with what 
we've configured for the client
        // TODO: check that "openid" is always included in the configured 
scopes, right?
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mod_auth_openidc-2.4.2.1/src/mod_auth_openidc.c 
new/mod_auth_openidc-2.4.3/src/mod_auth_openidc.c
--- old/mod_auth_openidc-2.4.2.1/src/mod_auth_openidc.c 2020-03-25 
13:09:26.000000000 +0100
+++ new/mod_auth_openidc-2.4.3/src/mod_auth_openidc.c   2020-06-10 
18:14:24.000000000 +0200
@@ -210,7 +210,7 @@
                        }
 
                        if (i == strip->nelts) {
-                               result = result ? apr_psprintf(r->pool, 
"%s%s%s", result,
+                               result = result ? apr_psprintf(r->pool, "%s%s 
%s", result,
                                                OIDC_STR_SEMI_COLON, cookie) :
                                                cookie;
                        }
@@ -227,7 +227,8 @@
 /*
  * calculates a hash value based on request fingerprint plus a provided nonce 
string.
  */
-static char *oidc_get_browser_state_hash(request_rec *r, const char *nonce) {
+static char *oidc_get_browser_state_hash(request_rec *r, oidc_cfg *c,
+               const char *nonce) {
 
        oidc_debug(r, "enter");
 
@@ -239,17 +240,21 @@
        /* Initialize the hash context */
        apr_sha1_init(&sha1);
 
-       /* get the X-FORWARDED-FOR header value  */
-       value = oidc_util_hdr_in_x_forwarded_for_get(r);
-       /* if we have a value for this header, concat it to the hash input */
-       if (value != NULL)
-               apr_sha1_update(&sha1, value, strlen(value));
+       if (c->state_input_headers & OIDC_STATE_INPUT_HEADERS_X_FORWARDED_FOR) {
+               /* get the X-FORWARDED-FOR header value  */
+               value = oidc_util_hdr_in_x_forwarded_for_get(r);
+               /* if we have a value for this header, concat it to the hash 
input */
+               if (value != NULL)
+                       apr_sha1_update(&sha1, value, strlen(value));
+       }
 
-       /* get the USER-AGENT header value  */
-       value = oidc_util_hdr_in_user_agent_get(r);
-       /* if we have a value for this header, concat it to the hash input */
-       if (value != NULL)
-               apr_sha1_update(&sha1, value, strlen(value));
+       if (c->state_input_headers & OIDC_STATE_INPUT_HEADERS_USER_AGENT) {
+               /* get the USER-AGENT header value  */
+               value = oidc_util_hdr_in_user_agent_get(r);
+               /* if we have a value for this header, concat it to the hash 
input */
+               if (value != NULL)
+                       apr_sha1_update(&sha1, value, strlen(value));
+       }
 
        /* get the remote client IP address or host name */
        /*
@@ -540,14 +545,13 @@
        oidc_jose_error_t err;
        oidc_jwk_t *jwk = NULL;
        if (oidc_util_create_symmetric_key(r, c->provider.client_secret,
-                       oidc_alg2keysize(alg), OIDC_JOSE_ALG_SHA256,
-                       TRUE, &jwk) == FALSE)
+                       oidc_alg2keysize(alg), OIDC_JOSE_ALG_SHA256, TRUE, 
&jwk) == FALSE)
                return FALSE;
 
        oidc_jwt_t *jwt = NULL;
        if (oidc_jwt_parse(r->pool, state, &jwt,
-                       oidc_util_merge_symmetric_key(r->pool, c->private_keys, 
jwk),
-                       &err) == FALSE) {
+                       oidc_util_merge_symmetric_key(r->pool, c->private_keys, 
jwk), &err)
+                       == FALSE) {
                oidc_error(r,
                                "could not parse JWT from state: invalid 
unsolicited response: %s",
                                oidc_jose_e2s(r->pool, err));
@@ -572,9 +576,10 @@
        }
 
        /* validate the state JWT, validating optional exp + iat */
-       if (oidc_proto_validate_jwt(r, jwt, provider->issuer, FALSE, FALSE,
-                       provider->idtoken_iat_slack,
-                       OIDC_TOKEN_BINDING_POLICY_DISABLED) == FALSE) {
+       if (oidc_proto_validate_jwt(r, jwt,
+                       provider->validate_issuer ? provider->issuer : NULL, 
FALSE, FALSE,
+                                       provider->idtoken_iat_slack,
+                                       OIDC_TOKEN_BINDING_POLICY_DISABLED) == 
FALSE) {
                oidc_jwt_destroy(jwt);
                return FALSE;
        }
@@ -598,8 +603,7 @@
 
        char *target_link_uri = NULL;
        oidc_jose_get_string(r->pool, jwt->payload.value.json,
-                       OIDC_CLAIM_TARGET_LINK_URI,
-                       FALSE, &target_link_uri, NULL);
+                       OIDC_CLAIM_TARGET_LINK_URI, FALSE, &target_link_uri, 
NULL);
        if (target_link_uri == NULL) {
                if (c->default_sso_url == NULL) {
                        oidc_error(r,
@@ -826,7 +830,7 @@
        const char *nonce = oidc_proto_state_get_nonce(*proto_state);
 
        /* calculate the hash of the browser fingerprint concatenated with the 
nonce */
-       char *calc = oidc_get_browser_state_hash(r, nonce);
+       char *calc = oidc_get_browser_state_hash(r, c, nonce);
        /* compare the calculated hash with the value provided in the 
authorization response */
        if (apr_strnatcmp(calc, state) != 0) {
                oidc_error(r,
@@ -1226,8 +1230,8 @@
 
        /* refresh the tokens by calling the token endpoint */
        if (oidc_proto_refresh_request(r, c, provider, refresh_token, 
&s_id_token,
-                       &s_access_token, &s_token_type, &expires_in,
-                       &s_refresh_token) == FALSE) {
+                       &s_access_token, &s_token_type, &expires_in, 
&s_refresh_token)
+                       == FALSE) {
                oidc_error(r, "access_token could not be refreshed");
                return FALSE;
        }
@@ -1306,7 +1310,8 @@
 
                                /* try again with the new access token */
                                if (oidc_proto_resolve_userinfo(r, c, provider, 
id_token_sub,
-                                               refreshed_access_token, 
&result, userinfo_jwt) == FALSE) {
+                                               refreshed_access_token, 
&result, userinfo_jwt)
+                                               == FALSE) {
 
                                        oidc_error(r,
                                                        "resolving user info 
claims with the refreshed access token failed, nothing will be stored in the 
session");
@@ -1481,7 +1486,8 @@
 }
 
 static apr_byte_t oidc_refresh_access_token_before_expiry(request_rec *r,
-               oidc_cfg *cfg, oidc_session_t *session, int ttl_minimum, int 
logout_on_error) {
+               oidc_cfg *cfg, oidc_session_t *session, int ttl_minimum,
+               int logout_on_error) {
 
        const char *s_access_token_expires = NULL;
        apr_time_t t_expires = -1;
@@ -1524,7 +1530,8 @@
 
        if (oidc_refresh_access_token(r, cfg, session, provider,
                        NULL) == FALSE) {
-               oidc_warn(r, "access_token could not be refreshed, logout=%d", 
logout_on_error & OIDC_LOGOUT_ON_ERROR_REFRESH);
+               oidc_warn(r, "access_token could not be refreshed, logout=%d",
+                               logout_on_error & OIDC_LOGOUT_ON_ERROR_REFRESH);
                if (logout_on_error & OIDC_LOGOUT_ON_ERROR_REFRESH)
                        return ERROR;
                else
@@ -2369,8 +2376,8 @@
        char *javascript = NULL, *javascript_method = NULL;
        char *html_head =
                        "<style type=\"text/css\">body {text-align: 
center}</style>";
-       if (oidc_post_preserve_javascript(r, NULL, &javascript,
-                       &javascript_method) == TRUE)
+       if (oidc_post_preserve_javascript(r, NULL, &javascript, 
&javascript_method)
+                       == TRUE)
                html_head = apr_psprintf(r->pool, "%s%s", html_head, 
javascript);
 
        /* now send the HTML contents to the user agent */
@@ -2437,7 +2444,7 @@
                oidc_proto_state_set_pkce_state(proto_state, pkce_state);
 
        /* get a hash value that fingerprints the browser concatenated with the 
random input */
-       char *state = oidc_get_browser_state_hash(r, nonce);
+       char *state = oidc_get_browser_state_hash(r, c, nonce);
 
        /*
         * create state that restores the context when the authorization 
response comes in
@@ -2613,8 +2620,8 @@
        }
 
        /* do open redirect prevention */
-       if (oidc_target_link_uri_matches_configuration(r, c,
-                       target_link_uri) == FALSE) {
+       if (oidc_target_link_uri_matches_configuration(r, c, target_link_uri)
+                       == FALSE) {
                return oidc_util_html_send_error(r, c->error_template,
                                "Invalid Request",
                                "\"target_link_uri\" parameter does not match 
configuration settings, aborting to prevent an open redirect.",
@@ -2669,7 +2676,8 @@
                }
 
                /* got an account name as input, perform OP discovery with that 
*/
-               if (oidc_proto_account_based_discovery(r, c, issuer, &issuer) 
== FALSE) {
+               if (oidc_proto_account_based_discovery(r, c, issuer, &issuer)
+                               == FALSE) {
 
                        /* something did not work out, show a user facing error 
*/
                        return oidc_util_html_send_error(r, c->error_template,
@@ -2912,15 +2920,15 @@
 
        // oidc_proto_validate_idtoken would try and require a token binding cnf
        // if the policy is set to "required", so don't use that here
-
-       if (oidc_proto_validate_jwt(r, jwt, provider->issuer, FALSE, FALSE,
-                       provider->idtoken_iat_slack,
-                       OIDC_TOKEN_BINDING_POLICY_DISABLED) == FALSE)
+       if (oidc_proto_validate_jwt(r, jwt,
+                       provider->validate_issuer ? provider->issuer : NULL, 
FALSE, FALSE,
+                                       provider->idtoken_iat_slack,
+                                       OIDC_TOKEN_BINDING_POLICY_DISABLED) == 
FALSE)
                goto out;
 
        /* verify the "aud" and "azp" values */
-       if (oidc_proto_validate_aud_and_azp(r, cfg, provider,
-                       &jwt->payload) == FALSE)
+       if (oidc_proto_validate_aud_and_azp(r, cfg, provider, &jwt->payload)
+                       == FALSE)
                goto out;
 
        json_t *events = json_object_get(jwt->payload.value.json,
@@ -3037,30 +3045,51 @@
        return rc;
 }
 
-static apr_byte_t oidc_validate_post_logout_url(request_rec *r, const char 
*url,
-               char **err_str, char **err_desc) {
+static apr_byte_t oidc_validate_redirect_url(request_rec *r, oidc_cfg *c,
+               const char *url, char **err_str, char **err_desc) {
        apr_uri_t uri;
        const char *c_host = NULL;
+       apr_hash_index_t *hi = NULL;
 
        if (apr_uri_parse(r->pool, url, &uri) != APR_SUCCESS) {
                *err_str = apr_pstrdup(r->pool, "Malformed URL");
-               *err_desc = apr_psprintf(r->pool, "Logout URL malformed: %s", 
url);
+               *err_desc = apr_psprintf(r->pool, "not a valid URL value: %s", 
url);
                oidc_error(r, "%s: %s", *err_str, *err_desc);
                return FALSE;
        }
 
-       c_host = oidc_get_current_url_host(r);
-       if ((uri.hostname != NULL)
-                       && ((strstr(c_host, uri.hostname) == NULL)
-                                       || (strstr(uri.hostname, c_host) == 
NULL))) {
-               *err_str = apr_pstrdup(r->pool, "Invalid Request");
-               *err_desc =
-                               apr_psprintf(r->pool,
-                                               "logout value \"%s\" does not 
match the hostname of the current request \"%s\"",
-                                               apr_uri_unparse(r->pool, &uri, 
0), c_host);
-               oidc_error(r, "%s: %s", *err_str, *err_desc);
-               return FALSE;
-       } else if ((uri.hostname == NULL) && (strstr(url, "/") != url)) {
+       if (c->redirect_urls_allowed != NULL) {
+               for (hi = apr_hash_first(NULL, c->redirect_urls_allowed); hi; 
hi =
+                               apr_hash_next(hi)) {
+                       apr_hash_this(hi, (const void**) &c_host, NULL, NULL);
+                       if (oidc_util_regexp_first_match(r->pool, url, c_host,
+                                       NULL, err_str) == TRUE)
+                               break;
+               }
+               if (hi == NULL) {
+                       *err_str = apr_pstrdup(r->pool, "URL not allowed");
+                       *err_desc =
+                                       apr_psprintf(r->pool,
+                                                       "value does not match 
the list of allowed redirect URLs: %s",
+                                                       url);
+                       oidc_error(r, "%s: %s", *err_str, *err_desc);
+                       return FALSE;
+               }
+       } else if (uri.hostname != NULL) {
+               c_host = oidc_get_current_url_host(r);
+               if ((strstr(c_host, uri.hostname) == NULL)
+                               || (strstr(uri.hostname, c_host) == NULL)) {
+                       *err_str = apr_pstrdup(r->pool, "Invalid Request");
+                       *err_desc =
+                                       apr_psprintf(r->pool,
+                                                       "URL value \"%s\" does 
not match the hostname of the current request \"%s\"",
+                                                       
apr_uri_unparse(r->pool, &uri, 0), c_host);
+                       oidc_error(r, "%s: %s", *err_str, *err_desc);
+                       return FALSE;
+               }
+       }
+
+       if ((uri.hostname == NULL) && (strstr(url, "/") != url)) {
                *err_str = apr_pstrdup(r->pool, "Malformed URL");
                *err_desc =
                                apr_psprintf(r->pool,
@@ -3068,30 +3097,26 @@
                                                url);
                oidc_error(r, "%s: %s", *err_str, *err_desc);
                return FALSE;
-        } else if ((uri.hostname == NULL) && (strstr(url, "//") == url)) {
-                *err_str = apr_pstrdup(r->pool, "Malformed URL");
-                *err_desc =
-                                apr_psprintf(r->pool,
-                                                "No hostname was parsed and 
starting with '//': %s",
-                                                url);
-                oidc_error(r, "%s: %s", *err_str, *err_desc);
-                return FALSE;
-        } else if ((uri.hostname == NULL) && (strstr(url, "/\\") == url)) {
-                *err_str = apr_pstrdup(r->pool, "Malformed URL");
-                *err_desc =
-                                apr_psprintf(r->pool,
-                                                "No hostname was parsed and 
starting with '/\\': %s",
-                                                url);
-                oidc_error(r, "%s: %s", *err_str, *err_desc);
-                return FALSE;
+       } else if ((uri.hostname == NULL) && (strstr(url, "//") == url)) {
+               *err_str = apr_pstrdup(r->pool, "Malformed URL");
+               *err_desc = apr_psprintf(r->pool,
+                               "No hostname was parsed and starting with '//': 
%s", url);
+               oidc_error(r, "%s: %s", *err_str, *err_desc);
+               return FALSE;
+       } else if ((uri.hostname == NULL) && (strstr(url, "/\\") == url)) {
+               *err_str = apr_pstrdup(r->pool, "Malformed URL");
+               *err_desc = apr_psprintf(r->pool,
+                               "No hostname was parsed and starting with 
'/\\': %s", url);
+               oidc_error(r, "%s: %s", *err_str, *err_desc);
+               return FALSE;
        }
 
        /* validate the URL to prevent HTTP header splitting */
        if (((strstr(url, "\n") != NULL) || strstr(url, "\r") != NULL)) {
-               *err_str = apr_pstrdup(r->pool, "Invalid Request");
+               *err_str = apr_pstrdup(r->pool, "Invalid URL");
                *err_desc =
                                apr_psprintf(r->pool,
-                                               "logout value \"%s\" contains 
illegal \"\n\" or \"\r\" character(s)",
+                                               "URL value \"%s\" contains 
illegal \"\n\" or \"\r\" character(s)",
                                                url);
                oidc_error(r, "%s: %s", *err_str, *err_desc);
                return FALSE;
@@ -3129,7 +3154,7 @@
        } else {
 
                /* do input validation on the logout parameter value */
-               if (oidc_validate_post_logout_url(r, url, &error_str,
+               if (oidc_validate_redirect_url(r, c, url, &error_str,
                                &error_description) == FALSE) {
                        return oidc_util_html_send_error(r, c->error_template, 
error_str,
                                        error_description,
@@ -3388,6 +3413,8 @@
        char *return_to = NULL;
        char *r_access_token = NULL;
        char *error_code = NULL;
+       char *error_str = NULL;
+       char *error_description = NULL;
 
        /* get the command passed to the session management handler */
        oidc_util_get_request_parameter(r, OIDC_REDIRECT_URI_REQUEST_REFRESH,
@@ -3402,6 +3429,14 @@
                return HTTP_INTERNAL_SERVER_ERROR;
        }
 
+       /* do input validation on the return to parameter value */
+       if (oidc_validate_redirect_url(r, c, return_to, &error_str,
+                       &error_description) == FALSE) {
+               oidc_error(r, "return_to URL validation failed: %s: %s", 
error_str,
+                               error_description);
+               return HTTP_INTERNAL_SERVER_ERROR;
+       }
+
        if (r_access_token == NULL) {
                oidc_error(r,
                                "refresh token request handler called with no 
access_token parameter");
@@ -3564,8 +3599,8 @@
 
                                /* get the current provider info */
                                oidc_provider_t *provider = NULL;
-                               if (oidc_get_provider_from_session(r, c, 
session,
-                                               &provider) == FALSE)
+                               if (oidc_get_provider_from_session(r, c, 
session, &provider)
+                                               == FALSE)
                                        return HTTP_INTERNAL_SERVER_ERROR;
 
                                /* execute the actual refresh grant */
@@ -3693,15 +3728,15 @@
 
                /* this is an authorization response from the OP using the 
Basic Client profile or a Hybrid flow*/
                return oidc_handle_redirect_authorization_response(r, c, 
session);
-       /*
-        *
-        * Note that we are checking for logout *before* checking for a POST 
authorization response
-        * to handle backchannel POST-based logout
-        *
-        * so any POST to the Redirect URI that does not have a logout query 
parameter will be handled
-        * as an authorization response; alternatively we could assume that a 
POST response has no
-        * parameters
-        */
+               /*
+                *
+                * Note that we are checking for logout *before* checking for a 
POST authorization response
+                * to handle backchannel POST-based logout
+                *
+                * so any POST to the Redirect URI that does not have a logout 
query parameter will be handled
+                * as an authorization response; alternatively we could assume 
that a POST response has no
+                * parameters
+                */
        } else if (oidc_util_request_has_parameter(r,
                        OIDC_REDIRECT_URI_REQUEST_LOGOUT)) {
                /* handle logout */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mod_auth_openidc-2.4.2.1/src/mod_auth_openidc.h 
new/mod_auth_openidc-2.4.3/src/mod_auth_openidc.h
--- old/mod_auth_openidc-2.4.2.1/src/mod_auth_openidc.h 2020-03-25 
13:09:26.000000000 +0100
+++ new/mod_auth_openidc-2.4.3/src/mod_auth_openidc.h   2020-06-10 
18:14:24.000000000 +0200
@@ -231,6 +231,9 @@
 #define OIDC_TOKEN_BINDING_POLICY_REQUIRED  2
 #define OIDC_TOKEN_BINDING_POLICY_ENFORCED  3
 
+#define OIDC_STATE_INPUT_HEADERS_USER_AGENT 1
+#define OIDC_STATE_INPUT_HEADERS_X_FORWARDED_FOR 2
+
 typedef apr_byte_t (*oidc_proto_pkce_state)(request_rec *r, char **state);
 typedef apr_byte_t (*oidc_proto_pkce_challenge)(request_rec *r, const char 
*state, char **code_challenge);
 typedef apr_byte_t (*oidc_proto_pkce_verifier)(request_rec *r, const char 
*state, char **code_verifier);
@@ -273,6 +276,7 @@
 
        // the next ones function as global default settings too
        int ssl_validate_server;
+       int validate_issuer;
        char *client_name;
        char *client_contact;
        char *registration_token;
@@ -417,6 +421,9 @@
        apr_hash_t *black_listed_claims;
        apr_hash_t *white_listed_claims;
 
+       apr_byte_t state_input_headers;
+
+       apr_hash_t *redirect_urls_allowed;
 } oidc_cfg;
 
 int oidc_check_user_id(request_rec *r);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mod_auth_openidc-2.4.2.1/src/parse.c 
new/mod_auth_openidc-2.4.3/src/parse.c
--- old/mod_auth_openidc-2.4.2.1/src/parse.c    2020-03-25 13:09:26.000000000 
+0100
+++ new/mod_auth_openidc-2.4.3/src/parse.c      2020-06-10 18:14:24.000000000 
+0200
@@ -1324,3 +1324,36 @@
        return oidc_parse_int_valid(pool, arg, int_value,
                        oidc_valid_refresh_access_token_before_expiry);
 }
+
+#define OIDC_STATE_INPUT_HEADERS_AS_BOTH            "both"
+#define OIDC_STATE_INPUT_HEADERS_AS_USER_AGENT      "user-agent"
+#define OIDC_STATE_INPUT_HEADERS_AS_X_FORWARDED_FOR "x-forwarded-for"
+#define OIDC_STATE_INPUT_HEADERS_AS_NONE            "none"
+
+/*
+ * parse a "set state input headers as" value from the provided string
+ */
+const char *oidc_parse_set_state_input_headers_as(apr_pool_t *pool, const char 
*arg,
+               apr_byte_t *state_input_headers) {
+       static char *options[] = {
+                       OIDC_STATE_INPUT_HEADERS_AS_BOTH,
+                       OIDC_STATE_INPUT_HEADERS_AS_USER_AGENT,
+                       OIDC_STATE_INPUT_HEADERS_AS_X_FORWARDED_FOR,
+                       OIDC_STATE_INPUT_HEADERS_AS_NONE,
+                       NULL };
+       const char *rv = oidc_valid_string_option(pool, arg, options);
+       if (rv != NULL)
+               return rv;
+
+       if (apr_strnatcmp(arg, OIDC_STATE_INPUT_HEADERS_AS_BOTH) == 0) {
+               *state_input_headers = OIDC_STATE_INPUT_HEADERS_USER_AGENT | 
OIDC_STATE_INPUT_HEADERS_X_FORWARDED_FOR;
+       } else if (apr_strnatcmp(arg, OIDC_STATE_INPUT_HEADERS_AS_USER_AGENT) 
== 0) {
+               *state_input_headers = OIDC_STATE_INPUT_HEADERS_USER_AGENT;
+       } else if (apr_strnatcmp(arg, 
OIDC_STATE_INPUT_HEADERS_AS_X_FORWARDED_FOR) == 0) {
+               *state_input_headers = OIDC_STATE_INPUT_HEADERS_X_FORWARDED_FOR;
+       } else if (apr_strnatcmp(arg, OIDC_STATE_INPUT_HEADERS_AS_NONE) == 0) {
+               *state_input_headers = 0;
+       }
+
+       return NULL;
+}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mod_auth_openidc-2.4.2.1/src/parse.h 
new/mod_auth_openidc-2.4.3/src/parse.h
--- old/mod_auth_openidc-2.4.2.1/src/parse.h    2020-03-25 13:09:26.000000000 
+0100
+++ new/mod_auth_openidc-2.4.3/src/parse.h      2020-06-10 18:14:24.000000000 
+0200
@@ -122,6 +122,7 @@
 const char *oidc_parse_auth_request_method(apr_pool_t *pool, const char *arg, 
int *method);
 const char *oidc_parse_max_number_of_state_cookies(apr_pool_t *pool, const 
char *arg1, const char *arg2, int *int_value, int *bool_value);
 const char *oidc_parse_refresh_access_token_before_expiry(apr_pool_t *pool, 
const char *arg, int *int_value);
+const char *oidc_parse_set_state_input_headers_as(apr_pool_t *pool, const char 
*arg, apr_byte_t *state_input_headers);
 
 typedef const char *(*oidc_valid_int_function_t)(apr_pool_t *, int);
 typedef const char *(*oidc_valid_function_t)(apr_pool_t *, const char *);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mod_auth_openidc-2.4.2.1/src/proto.c 
new/mod_auth_openidc-2.4.3/src/proto.c
--- old/mod_auth_openidc-2.4.2.1/src/proto.c    2020-03-25 13:09:26.000000000 
+0100
+++ new/mod_auth_openidc-2.4.3/src/proto.c      2020-06-10 18:14:24.000000000 
+0200
@@ -1354,7 +1354,7 @@
        }
 
        /* validate the ID Token JWT, requiring iss match, and valid exp + iat 
*/
-       if (oidc_proto_validate_jwt(r, jwt, provider->issuer, TRUE, TRUE,
+       if (oidc_proto_validate_jwt(r, jwt, provider->validate_issuer ? 
provider->issuer : NULL, TRUE, TRUE,
                        provider->idtoken_iat_slack,
                        provider->token_binding_policy) == FALSE)
                return FALSE;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mod_auth_openidc-2.4.2.1/src/util.c 
new/mod_auth_openidc-2.4.3/src/util.c
--- old/mod_auth_openidc-2.4.2.1/src/util.c     2020-03-25 13:09:26.000000000 
+0100
+++ new/mod_auth_openidc-2.4.3/src/util.c       2020-06-10 18:14:24.000000000 
+0200
@@ -2267,14 +2267,18 @@
                goto out;
        }
 
-       if (pcre_get_substring(input, subStr, rc, OIDC_UTIL_REGEXP_MATCH_NR,
-                       &(psubStrMatchStr)) <= 0) {
-               *error_str = apr_psprintf(pool, "pcre_get_substring failed 
(rc=%d)",
-                               rc);
-               goto out;
+       if (output) {
+
+               if (pcre_get_substring(input, subStr, rc, 
OIDC_UTIL_REGEXP_MATCH_NR,
+                               &(psubStrMatchStr)) <= 0) {
+                       *error_str = apr_psprintf(pool, "pcre_get_substring 
failed (rc=%d)",
+                                       rc);
+                       goto out;
+               }
+
+               *output = apr_pstrdup(pool, psubStrMatchStr);
        }
 
-       *output = apr_pstrdup(pool, psubStrMatchStr);
        rv = TRUE;
 
 out:


Reply via email to