Skip to content

Commit d4e282e

Browse files
committed
compare hostnames and domains in a case insensitive way
cookie: fix oidc_util_cookie_domain_valid to check the actual request bump to 2.4.16.10dev Signed-off-by: Hans Zandbelt <[email protected]>
1 parent 8dd6c86 commit d4e282e

File tree

9 files changed

+51
-32
lines changed

9 files changed

+51
-32
lines changed

ChangeLog

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
1+
03/20/2025
2+
- core: compare hostnames and domains in a case insensitive way in:
3+
oidc_request_check_cookie_domain
4+
oidc_util_cookie_domain_valid
5+
oidc_validate_redirect_url
6+
oidc_cfg_parse_is_valid_url_scheme
7+
oidc_discovery_target_link_uri_match
8+
- cookie: fix oidc_util_cookie_domain_valid so that it checks the incoming request against OIDCCookieDomain
9+
rather than the OIDCRedirectURI and displays the correct error message if they don't match
10+
- bump to 2.4.16.10dev
11+
112
03/19/2025
213
- release 2.4.16.9
314

415
03/18/2025
5-
- core: use case insensitive hostname/domain comparison in oidc_check_cookie_domain
16+
- cookie: use case insensitive hostname/domain comparison in oidc_check_cookie_domain
617
- authz: remove the Location header from HTML based step up authentication redirects
718
as it may conflict with its HTTP 200 status code and confuse middle boxes
819
- metrics: avoid double-free on shutdown by not calling pthread_exit; fixes #1207; thanks @studersi

configure.ac

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
AC_INIT([mod_auth_openidc],[2.4.16.9],[[email protected]])
1+
AC_INIT([mod_auth_openidc],[2.4.16.10dev],[[email protected]])
22

33
AC_SUBST(NAMEVER, AC_PACKAGE_TARNAME()-AC_PACKAGE_VERSION())
44

src/cfg/parse.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,8 @@ static const char *oidc_cfg_parse_is_valid_url_scheme(apr_pool_t *pool, const ch
213213
if (uri.scheme == NULL)
214214
return apr_psprintf(pool, "'%s' cannot be parsed as a URL (no scheme set)", arg);
215215

216-
if ((scheme1 != NULL) && (_oidc_strcmp(uri.scheme, scheme1) != 0)) {
217-
if ((scheme2 != NULL) && (_oidc_strcmp(uri.scheme, scheme2) != 0)) {
216+
if ((scheme1 != NULL) && (_oidc_strnatcasecmp(uri.scheme, scheme1) != 0)) {
217+
if ((scheme2 != NULL) && (_oidc_strnatcasecmp(uri.scheme, scheme2) != 0)) {
218218
return apr_psprintf(pool, "'%s' cannot be parsed as a \"%s\" or \"%s\" URL (scheme == %s)!",
219219
arg, scheme1, scheme2, uri.scheme);
220220
} else if (scheme2 == NULL) {

src/handle/discovery.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -247,9 +247,9 @@ static int oidc_discovery_target_link_uri_match(request_rec *r, oidc_cfg_t *cfg,
247247
if (oidc_cfg_cookie_domain_get(cfg) == NULL) {
248248
/* cookie_domain set: see if the target_link_uri matches the redirect_uri host (because the session
249249
* cookie will be set host-wide) */
250-
if (_oidc_strcmp(o_uri.hostname, r_uri.hostname) != 0) {
251-
char *p = _oidc_strstr(o_uri.hostname, r_uri.hostname);
252-
if ((p == NULL) || (_oidc_strcmp(r_uri.hostname, p) != 0)) {
250+
if (_oidc_strnatcasecmp(o_uri.hostname, r_uri.hostname) != 0) {
251+
const char *p = oidc_util_strcasestr(o_uri.hostname, r_uri.hostname);
252+
if ((p == NULL) || (_oidc_strnatcasecmp(r_uri.hostname, p) != 0)) {
253253
oidc_error(r,
254254
"the URL hostname (%s) of the configured " OIDCRedirectURI
255255
" does not match the URL hostname of the \"target_link_uri\" (%s): aborting "
@@ -260,8 +260,8 @@ static int oidc_discovery_target_link_uri_match(request_rec *r, oidc_cfg_t *cfg,
260260
}
261261
} else {
262262
/* cookie_domain set: see if the target_link_uri is within the cookie_domain */
263-
char *p = _oidc_strstr(o_uri.hostname, oidc_cfg_cookie_domain_get(cfg));
264-
if ((p == NULL) || (_oidc_strcmp(oidc_cfg_cookie_domain_get(cfg), p) != 0)) {
263+
const char *p = oidc_util_strcasestr(o_uri.hostname, oidc_cfg_cookie_domain_get(cfg));
264+
if ((p == NULL) || (_oidc_strnatcasecmp(oidc_cfg_cookie_domain_get(cfg), p) != 0)) {
265265
oidc_error(r,
266266
"the domain (%s) configured in " OIDCCookieDomain
267267
" does not match the URL hostname (%s) of the \"target_link_uri\" (%s): aborting to "

src/handle/handle.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ int oidc_request_uri(request_rec *r, oidc_cfg_t *c);
108108
int oidc_request_authenticate_user(request_rec *r, oidc_cfg_t *c, oidc_provider_t *provider, const char *original_url,
109109
const char *login_hint, const char *id_token_hint, const char *prompt,
110110
const char *auth_request_params, const char *path_scope);
111+
apr_byte_t oidc_request_check_cookie_domain(request_rec *r, oidc_cfg_t *c, const char *original_url);
111112

112113
// response.c
113114
apr_byte_t oidc_response_post_preserve_javascript(request_rec *r, const char *location, char **javascript,

src/handle/request.c

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@
4747
#include "state.h"
4848
#include "util.h"
4949

50-
static int oidc_request_check_cookie_domain(request_rec *r, oidc_cfg_t *c, oidc_proto_state_t *proto_state,
51-
const char *original_url) {
50+
apr_byte_t oidc_request_check_cookie_domain(request_rec *r, oidc_cfg_t *c, const char *original_url) {
5251
/*
5352
* printout errors if Cookie settings are not going to work
5453
*/
@@ -58,44 +57,41 @@ static int oidc_request_check_cookie_domain(request_rec *r, oidc_cfg_t *c, oidc_
5857
_oidc_memset(&r_uri, 0, sizeof(apr_uri_t));
5958
apr_uri_parse(r->pool, original_url, &o_uri);
6059
apr_uri_parse(r->pool, oidc_util_redirect_uri(r, c), &r_uri);
61-
if ((_oidc_strcmp(o_uri.scheme, r_uri.scheme) != 0) && (_oidc_strcmp(r_uri.scheme, "https") == 0)) {
60+
if ((_oidc_strnatcasecmp(o_uri.scheme, r_uri.scheme) != 0) && (_oidc_strcmp(r_uri.scheme, "https") == 0)) {
6261
oidc_error(r,
6362
"the URL scheme (%s) of the configured " OIDCRedirectURI
6463
" does not match the URL scheme of the URL being accessed (%s): the \"state\" and "
6564
"\"session\" cookies will not be shared between the two!",
6665
r_uri.scheme, o_uri.scheme);
67-
oidc_proto_state_destroy(proto_state);
68-
return HTTP_INTERNAL_SERVER_ERROR;
66+
return FALSE;
6967
}
7068

7169
if (oidc_cfg_cookie_domain_get(c) == NULL) {
72-
if (_oidc_strcmp(o_uri.hostname, r_uri.hostname) != 0) {
70+
if (_oidc_strnatcasecmp(o_uri.hostname, r_uri.hostname) != 0) {
7371
char *p = _oidc_strstr(o_uri.hostname, r_uri.hostname);
7472
if ((p == NULL) || (_oidc_strcmp(r_uri.hostname, p) != 0)) {
7573
oidc_error(r,
7674
"the URL hostname (%s) of the configured " OIDCRedirectURI
7775
" does not match the URL hostname of the URL being accessed (%s): the "
7876
"\"state\" and \"session\" cookies will not be shared between the two!",
7977
r_uri.hostname, o_uri.hostname);
80-
oidc_proto_state_destroy(proto_state);
8178
OIDC_METRICS_COUNTER_INC(r, c, OM_AUTHN_REQUEST_ERROR_URL);
82-
return HTTP_INTERNAL_SERVER_ERROR;
79+
return FALSE;
8380
}
8481
}
8582
} else {
86-
if (!oidc_util_cookie_domain_valid(r_uri.hostname, oidc_cfg_cookie_domain_get(c))) {
83+
if (!oidc_util_cookie_domain_valid(o_uri.hostname, oidc_cfg_cookie_domain_get(c))) {
8784
oidc_error(r,
8885
"the domain (%s) configured in " OIDCCookieDomain
8986
" does not match the URL hostname (%s) of the URL being accessed (%s): setting "
9087
"\"state\" and \"session\" cookies will not work!!",
9188
oidc_cfg_cookie_domain_get(c), o_uri.hostname, original_url);
92-
oidc_proto_state_destroy(proto_state);
9389
OIDC_METRICS_COUNTER_INC(r, c, OM_AUTHN_REQUEST_ERROR_URL);
94-
return HTTP_INTERNAL_SERVER_ERROR;
90+
return FALSE;
9591
}
9692
}
9793

98-
return OK;
94+
return TRUE;
9995
}
10096

10197
static const char *oidc_request_samesite_cookie(request_rec *r, struct oidc_cfg_t *c) {
@@ -248,10 +244,9 @@ int oidc_request_authenticate_user(request_rec *r, oidc_cfg_t *c, oidc_provider_
248244
return rc;
249245
}
250246

251-
rc = oidc_request_check_cookie_domain(r, c, proto_state, original_url);
252-
if (rc != OK) {
247+
if (oidc_request_check_cookie_domain(r, c, original_url) == FALSE) {
253248
oidc_proto_state_destroy(proto_state);
254-
return rc;
249+
return HTTP_INTERNAL_SERVER_ERROR;
255250
}
256251

257252
/* send off to the OpenID Connect Provider */

src/mod_auth_openidc.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -888,7 +888,8 @@ apr_byte_t oidc_validate_redirect_url(request_rec *r, oidc_cfg_t *c, const char
888888
url_ipv6_aware = uri.hostname;
889889
}
890890

891-
if ((_oidc_strstr(c_host, url_ipv6_aware) == NULL) || (_oidc_strstr(url_ipv6_aware, c_host) == NULL)) {
891+
if ((oidc_util_strcasestr(c_host, url_ipv6_aware) == NULL) ||
892+
(oidc_util_strcasestr(url_ipv6_aware, c_host) == NULL)) {
892893
*err_str = apr_pstrdup(r->pool, "Invalid Request");
893894
*err_desc = apr_psprintf(
894895
r->pool, "URL value \"%s\" does not match the hostname of the current request \"%s\"",
@@ -898,19 +899,19 @@ apr_byte_t oidc_validate_redirect_url(request_rec *r, oidc_cfg_t *c, const char
898899
}
899900
}
900901

901-
if ((uri.hostname == NULL) && (_oidc_strstr(url, "/") != url)) {
902+
if ((uri.hostname == NULL) && (oidc_util_strcasestr(url, "/") != url)) {
902903
*err_str = apr_pstrdup(r->pool, "Malformed URL");
903904
*err_desc = apr_psprintf(
904905
r->pool, "No hostname was parsed and it does not seem to be relative, i.e starting with '/': %s",
905906
url);
906907
oidc_error(r, "%s: %s", *err_str, *err_desc);
907908
return FALSE;
908-
} else if ((uri.hostname == NULL) && (_oidc_strstr(url, "//") == url)) {
909+
} else if ((uri.hostname == NULL) && (oidc_util_strcasestr(url, "//") == url)) {
909910
*err_str = apr_pstrdup(r->pool, "Malformed URL");
910911
*err_desc = apr_psprintf(r->pool, "No hostname was parsed and starting with '//': %s", url);
911912
oidc_error(r, "%s: %s", *err_str, *err_desc);
912913
return FALSE;
913-
} else if ((uri.hostname == NULL) && (_oidc_strstr(url, "/\\") == url)) {
914+
} else if ((uri.hostname == NULL) && (oidc_util_strcasestr(url, "/\\") == url)) {
914915
*err_str = apr_pstrdup(r->pool, "Malformed URL");
915916
*err_desc = apr_psprintf(r->pool, "No hostname was parsed and starting with '/\\': %s", url);
916917
oidc_error(r, "%s: %s", *err_str, *err_desc);

src/util.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1989,15 +1989,15 @@ apr_byte_t oidc_util_regexp_first_match(apr_pool_t *pool, const char *input, con
19891989
* check if the provided cookie domain value is valid
19901990
*/
19911991
apr_byte_t oidc_util_cookie_domain_valid(const char *hostname, const char *cookie_domain) {
1992-
char *p = NULL;
1992+
const char *p = NULL;
19931993
const char *check_cookie = cookie_domain;
19941994
// Skip past the first char of a cookie_domain that starts
19951995
// with a ".", ASCII 46
19961996
if (check_cookie[0] == 46)
19971997
check_cookie++;
1998-
p = _oidc_strstr(hostname, check_cookie);
1998+
p = oidc_util_strcasestr(hostname, check_cookie);
19991999

2000-
if ((p == NULL) || (_oidc_strcmp(check_cookie, p) != 0)) {
2000+
if ((p == NULL) || (_oidc_strnatcasecmp(check_cookie, p) != 0)) {
20012001
return FALSE;
20022002
}
20032003
return TRUE;

test/test.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1782,9 +1782,20 @@ static char *test_check_cookie_domain(request_rec *r) {
17821782
apr_table_set(r->headers_in, "Host", "ab001SB161djbn.xyz.com");
17831783

17841784
rv = oidc_check_cookie_domain(r, c, session);
1785-
17861785
TST_ASSERT_BYTE("oidc_check_cookie_domain", rv, TRUE);
17871786

1787+
rv = oidc_request_check_cookie_domain(r, c, "https://WWW.example.com/protected/index.html");
1788+
TST_ASSERT_BYTE("oidc_request_check_cookie_domain", rv, TRUE);
1789+
1790+
c->cookie_domain = ".XYZ.com";
1791+
rv = oidc_request_check_cookie_domain(r, c, "https://ab001sb161djbn.xyz.com/protected/index.html");
1792+
TST_ASSERT_BYTE("oidc_request_check_cookie_domain", rv, TRUE);
1793+
1794+
c->cookie_domain = "ab001SB161djbn.xyz.com";
1795+
rv = oidc_request_check_cookie_domain(r, c, "https://ab001sb161djbn.xyz.com/protected/index.html");
1796+
TST_ASSERT_BYTE("oidc_request_check_cookie_domain", rv, TRUE);
1797+
1798+
c->cookie_domain = NULL;
17881799
oidc_session_free(r, session);
17891800

17901801
return 0;

0 commit comments

Comments
 (0)