Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package apache2-mod_auth_openidc for
openSUSE:Factory checked in at 2021-07-23 23:41:20
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/apache2-mod_auth_openidc (Old)
and /work/SRC/openSUSE:Factory/.apache2-mod_auth_openidc.new.1899 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "apache2-mod_auth_openidc"
Fri Jul 23 23:41:20 2021 rev:19 rq:907973 version:2.4.9
Changes:
--------
---
/work/SRC/openSUSE:Factory/apache2-mod_auth_openidc/apache2-mod_auth_openidc.changes
2021-05-19 17:49:25.813522031 +0200
+++
/work/SRC/openSUSE:Factory/.apache2-mod_auth_openidc.new.1899/apache2-mod_auth_openidc.changes
2021-07-23 23:41:43.913791464 +0200
@@ -1,0 +2,48 @@
+Fri Jul 23 07:46:56 UTC 2021 - Michael Str??der <[email protected]>
+
+- Update to version 2.4.9
+ * Security
+ - use redisvCommand to avoid crash with crafted key when using Redis
+ without encryption; thanks @thomas-chauchefoin-sonarsource
+ - replace potentially harmful backslashes with forward slashes when
+ validating redirection URLs; thanks @thomas-chauchefoin-sonarsource
+ - avoid XSS vulnerability when using OIDCPreservePost On and supplying
+ URLs that contain single quotes; thanks @oss-aimoto
+ - return OK in the content handler for calls to the redirect URI and when
+ preserving POST data; prevent (intermittent) disclosure of content
+ hosted at a (non-vanity) redirect URI location
+ - use encrypted JWTs for storing encrypted cache contents and
+ avoid using static AAD/IV; thanks @niebardzo
+ * Bugfixes
+ - verify that alg is not none in logout_token explicitly
+ - don't clear POST params authn on token revocation; thanks @iainh
+ - fix a problem where the host and port are calculated incorrectly when
using literal ipv6 address.
+ * Other
+ - make session not found on backchannel logout produce a log warning
instead of error
+ - handle discovery in the content handler
+ - strip A256GCM JWT header from encrypted JWTs used for state cookies,
+ cache encryption and by-value session cookies resulting in smaller
+ cookies and reduced cache content size
+- Fix CVE-2021-32785 format string bug via hiredis
+ (CVE-2021-32785, bsc#1188638)
+- Fix CVE-2021-32786 open redirect in logout functionality
+ (CVE-2021-32786, bsc#1188639)
+
+-------------------------------------------------------------------
+Wed Jun 2 19:04:56 UTC 2021 - Michael Str??der <[email protected]>
+
+- Use autogen.sh to generate missing configure script
+- Update to version 2.4.8.4
+ * Bugfixes
+ - do not send state timeout HTML document when OIDCDefaultURL is set;
+ this can be overridden by using e.g.:
+ SetEnvIfExpr true OIDC_NO_DEFAULT_URL_ON_STATE_TIMEOUT=true
+ - avoid Apache 2.4 appending 400/302(200/404) HTML document text to
+ state timeout HTML info page see also f5959d7 and #484; at least Debian
+ Buster was affected
+ * Other
+ - make error "session corrupted: no issuer found in session" a warning
+ only so a logout call for a non-existing session no longer produces
+ error messages
+
+-------------------------------------------------------------------
Old:
----
mod_auth_openidc-2.4.8.2.tar.gz
New:
----
mod_auth_openidc-2.4.9.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ apache2-mod_auth_openidc.spec ++++++
--- /var/tmp/diff_new_pack.S0cbAC/_old 2021-07-23 23:41:44.373790876 +0200
+++ /var/tmp/diff_new_pack.S0cbAC/_new 2021-07-23 23:41:44.373790876 +0200
@@ -17,7 +17,7 @@
Name: apache2-mod_auth_openidc
-Version: 2.4.8.2
+Version: 2.4.9
Release: 0
Summary: Apache2.x module for an OpenID Connect enabled Identity
Provider
License: Apache-2.0
@@ -26,6 +26,8 @@
Source:
https://github.com/zmartzone/mod_auth_openidc/releases/download/v%{version}/mod_auth_openidc-%{version}.tar.gz
BuildRequires: apache-rpm-macros
BuildRequires: apache2-devel
+BuildRequires: autoconf
+BuildRequires: automake
BuildRequires: pkgconfig
BuildRequires: pkgconfig(cjose) >= 0.5.1
BuildRequires: pkgconfig(jansson) >= 2.0
@@ -45,6 +47,7 @@
%setup -q -n mod_auth_openidc-%{version}
%build
+./autogen.sh
%configure \
%if 0%{?is_opensuse} > 0
%{?_with_hiredis} \
++++++ mod_auth_openidc-2.4.8.2.tar.gz -> mod_auth_openidc-2.4.9.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/mod_auth_openidc-2.4.8.2/AUTHORS
new/mod_auth_openidc-2.4.9/AUTHORS
--- old/mod_auth_openidc-2.4.8.2/AUTHORS 2021-05-12 11:00:34.000000000
+0200
+++ new/mod_auth_openidc-2.4.9/AUTHORS 2021-07-22 18:30:00.000000000 +0200
@@ -70,3 +70,7 @@
Harri Rautila <https://github.com/hrautila>
Tatsuhiko Yasumatsu <https://github.com/ty60>
Adam Stadler <https://github.com/tzfx>
+ Steffen Greber <https://github.com/codemaker219>
+ Iain Heggie <https://github.com/iainh>
+
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/mod_auth_openidc-2.4.8.2/ChangeLog
new/mod_auth_openidc-2.4.9/ChangeLog
--- old/mod_auth_openidc-2.4.8.2/ChangeLog 2021-05-13 09:30:00.000000000
+0200
+++ new/mod_auth_openidc-2.4.9/ChangeLog 2021-07-22 18:30:21.000000000
+0200
@@ -1,3 +1,48 @@
+07/22/2021
+- use redisvCommand to avoid crash with crafted key when using Redis without
encryption; thanks @thomas-chauchefoin-sonarsource
+- replace potentially harmful backslashes with forward slashes when validating
redirection URLs; thanks @thomas-chauchefoin-sonarsource
+- release 2.4.9
+
+07/15/2021
+- verify that "alg" is not none in logout_token explicitly
+- make session not found on backchannel logout produce a log warning instead
of error
+- don't clear POST params authn on token revocation; thanks @iainh
+- bump to 2.4.9rc0
+
+closes #626
+07/02/2021
+- handle discovery in the content handler
+- return OK in the content handler for calls to the redirect URI and when
preserving POST data
+
+06/25/2021
+- avoid XSS vulnerability when using OIDCPreservePost On and supplying URLs
that contain single quotes
+ thanks @oss-aimoto
+
+06/21/2021
+- strip A256GCM JWT header from encrypted JWTS used for state cookies, cache
encryption and by-value session cookies
+ resulting in smaller cookies and reduced cache content size
+
+06/10/2021
+- use encrypted JWTs for storing encrypted cache contents and avoid using
static AAD/IV; thanks @niebardzo
+- bump to 2.4.9-dev
+
+06/04/2021
+- fix a problem where the host and port are calculated incorrectly, when you
use literal ipv6 address.
+
+06/02/2021
+- do not send state timeout HTML document when OIDCDefaultURL is set; this can
be overridden by using e.g.:
+ SetEnvIfExpr true OIDC_NO_DEFAULT_URL_ON_STATE_TIMEOUT=true
+- release 2.4.8.4
+
+06/01/2021
+- avoid Apache 2.4 appending 400/302(200/404) HTML document text to state
timeout HTML info page
+ see also f5959d767b0eec4856d561cbaa6d2262a52da551 and #484; at least Debian
Buster was affected
+- release 2.4.8.3
+
+05/18/2021
+- make error "session corrupted: no issuer found in session" a warning only so
a logout call for a
+ non-existing session no longer produces error messages
+
05/08/2021
- store timestamps in session in seconds to avoid string conversion problems
on some (libapr-1)
platform build/run combinations, causing "maximum session duration exceeded"
errors
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/mod_auth_openidc-2.4.8.2/auth_openidc.conf
new/mod_auth_openidc-2.4.9/auth_openidc.conf
--- old/mod_auth_openidc-2.4.8.2/auth_openidc.conf 2021-05-07
16:02:08.000000000 +0200
+++ new/mod_auth_openidc-2.4.9/auth_openidc.conf 2021-07-22
18:30:00.000000000 +0200
@@ -585,8 +585,7 @@
# c) validated OAuth 2.0 tokens
# d) JWK sets that have been retrieved from jwk_uri's
# e) resolved OP metadata when using OIDCProviderMetadataUrl
-# f) JWT ID claims (jti) when using OP-init-SSO
-# g) temporary state associated with Request URI's
+# f) temporary state associated with Request URI's
# must be one of \"shm\", \"memcache\", \"file\" or, if Redis support is
compiled in, \"redis\"
# When not defined, "shm" (shared memory) is used.
#OIDCCacheType [shm|memcache|file[|redis]]
@@ -678,10 +677,16 @@
# When not defined a bare-bones internal template is used.
#OIDCHTMLErrorTemplate <filename>
-# Defines a default URL to be used in case of 3rd-party or OP initiated
-# SSO when no explicit target_link_uri has been provided. The user is also
-# sent to this URL is in case an invalid authorization response was received.
-# When not defined, 3rd-party SSO must be done with a specified
\"target_link_uri\" parameter.
+# Defines a default URL to be used in case of 3rd-party-init-SSO when no
explicit target_link_uri
+# has been provided. The user is also redirected to this URL in case an
invalid authorization
+# response was received.
+#
+# By default, when no OIDCDefaultURL is set, an expired state cookie will lead
to an HTML error page
+# being sent to the browser explaining what happened. To copy that (legacy)
behaviour when OIDCDefaultURL is set,
+# so that the browser is no longer redirected to the OIDCDefaultURL in case of
state cookie expiry, use:
+# SetEnvIfExpr true OIDC_NO_DEFAULT_URL_ON_STATE_TIMEOUT=true
+#
+# The default is to not redirect the browser to any URL but return an
HTTP/HTML error to the user.
#OIDCDefaultURL <default-url>
# Defines a default URL where the user is sent to after logout, which may be
overridden explicitly during logout.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/mod_auth_openidc-2.4.8.2/configure
new/mod_auth_openidc-2.4.9/configure
--- old/mod_auth_openidc-2.4.8.2/configure 2021-05-18 07:51:25.000000000
+0200
+++ new/mod_auth_openidc-2.4.9/configure 2021-07-22 18:41:17.000000000
+0200
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.71 for mod_auth_openidc 2.4.8.2.
+# Generated by GNU Autoconf 2.71 for mod_auth_openidc 2.4.9.
#
# Report bugs to <[email protected]>.
#
@@ -610,8 +610,8 @@
# Identity of this package.
PACKAGE_NAME='mod_auth_openidc'
PACKAGE_TARNAME='mod_auth_openidc'
-PACKAGE_VERSION='2.4.8.2'
-PACKAGE_STRING='mod_auth_openidc 2.4.8.2'
+PACKAGE_VERSION='2.4.9'
+PACKAGE_STRING='mod_auth_openidc 2.4.9'
PACKAGE_BUGREPORT='[email protected]'
PACKAGE_URL=''
@@ -1301,7 +1301,7 @@
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures mod_auth_openidc 2.4.8.2 to adapt to many kinds of
systems.
+\`configure' configures mod_auth_openidc 2.4.9 to adapt to many kinds of
systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1364,7 +1364,7 @@
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of mod_auth_openidc 2.4.8.2:";;
+ short | recursive ) echo "Configuration of mod_auth_openidc 2.4.9:";;
esac
cat <<\_ACEOF
@@ -1478,7 +1478,7 @@
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-mod_auth_openidc configure 2.4.8.2
+mod_auth_openidc configure 2.4.9
generated by GNU Autoconf 2.71
Copyright (C) 2021 Free Software Foundation, Inc.
@@ -1634,7 +1634,7 @@
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by mod_auth_openidc $as_me 2.4.8.2, which was
+It was created by mod_auth_openidc $as_me 2.4.9, which was
generated by GNU Autoconf 2.71. Invocation command line was
$ $0$ac_configure_args_raw
@@ -2292,7 +2292,7 @@
-NAMEVER=mod_auth_openidc-2.4.8.2
+NAMEVER=mod_auth_openidc-2.4.9
# This section defines the --with-apxs2 option.
@@ -4952,7 +4952,7 @@
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by mod_auth_openidc $as_me 2.4.8.2, which was
+This file was extended by mod_auth_openidc $as_me 2.4.9, which was
generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -5007,7 +5007,7 @@
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
-mod_auth_openidc config.status 2.4.8.2
+mod_auth_openidc config.status 2.4.9
configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/mod_auth_openidc-2.4.8.2/configure.ac
new/mod_auth_openidc-2.4.9/configure.ac
--- old/mod_auth_openidc-2.4.8.2/configure.ac 2021-05-13 09:30:00.000000000
+0200
+++ new/mod_auth_openidc-2.4.9/configure.ac 2021-07-22 18:30:33.000000000
+0200
@@ -1,4 +1,4 @@
-AC_INIT([mod_auth_openidc],[2.4.8.2],[[email protected]])
+AC_INIT([mod_auth_openidc],[2.4.9],[[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.8.2/src/cache/common.c
new/mod_auth_openidc-2.4.9/src/cache/common.c
--- old/mod_auth_openidc-2.4.8.2/src/cache/common.c 2021-05-07
23:27:25.000000000 +0200
+++ new/mod_auth_openidc-2.4.9/src/cache/common.c 2021-07-22
18:30:00.000000000 +0200
@@ -244,325 +244,59 @@
return rv;
}
-#define oidc_cache_crypto_openssl_error(r, fmt, ...) \
- oidc_error(r, "%s: %s", apr_psprintf(r->pool, fmt,
##__VA_ARGS__), ERR_error_string(ERR_get_error(), NULL))
-
-#define OIDC_CACHE_CIPHER
EVP_aes_256_gcm()
-#define OIDC_CACHE_TAG_LEN
16
-
-#if (OPENSSL_VERSION_NUMBER >= 0x10100005L &&
!defined(LIBRESSL_VERSION_NUMBER))
-#define OIDC_CACHE_CRYPTO_GET_TAG
EVP_CTRL_AEAD_GET_TAG
-#define OIDC_CACHE_CRYPTO_SET_TAG
EVP_CTRL_AEAD_SET_TAG
-#define OIDC_CACHE_CRYPTO_SET_IVLEN
EVP_CTRL_AEAD_SET_IVLEN
-#else
-#define OIDC_CACHE_CRYPTO_GET_TAG
EVP_CTRL_GCM_GET_TAG
-#define OIDC_CACHE_CRYPTO_SET_TAG
EVP_CTRL_GCM_SET_TAG
-#define OIDC_CACHE_CRYPTO_SET_IVLEN
EVP_CTRL_GCM_SET_IVLEN
-#endif
-
-/*
- * AES GCM encrypt
- */
-static int oidc_cache_crypto_encrypt_impl(request_rec *r,
- unsigned char *plaintext, int plaintext_len, const unsigned
char *aad,
- int aad_len, unsigned char *key, const unsigned char *iv, int
iv_len,
- unsigned char *ciphertext, const unsigned char *tag, int
tag_len) {
- EVP_CIPHER_CTX *ctx;
-
- int len;
-
- int ciphertext_len;
-
- /* create and initialize the context */
- if (!(ctx = EVP_CIPHER_CTX_new())) {
- oidc_cache_crypto_openssl_error(r, "EVP_CIPHER_CTX_new");
- return -1;
- }
-
- /* initialize the encryption cipher */
- if (!EVP_EncryptInit_ex(ctx, OIDC_CACHE_CIPHER, NULL, NULL, NULL)) {
- oidc_cache_crypto_openssl_error(r, "EVP_EncryptInit_ex");
- return -1;
- }
-
- /* set IV length */
- if (!EVP_CIPHER_CTX_ctrl(ctx, OIDC_CACHE_CRYPTO_SET_IVLEN, iv_len,
NULL)) {
- oidc_cache_crypto_openssl_error(r, "EVP_CIPHER_CTX_ctrl");
- return -1;
- }
-
- /* initialize key and IV */
- if (!EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) {
- oidc_cache_crypto_openssl_error(r, "EVP_EncryptInit_ex");
- return -1;
- }
-
- /* provide AAD data */
- if (!EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_len)) {
- oidc_cache_crypto_openssl_error(r, "EVP_DecryptUpdate aad:
aad_len=%d",
- aad_len);
- return -1;
- }
-
- /* provide the message to be encrypted and obtain the encrypted output
*/
- if (!EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext,
plaintext_len)) {
- oidc_cache_crypto_openssl_error(r, "EVP_EncryptUpdate
ciphertext");
- return -1;
- }
- ciphertext_len = len;
-
- /*
- * finalize the encryption; normally ciphertext bytes may be written at
- * this stage, but this does not occur in GCM mode
- */
- if (!EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) {
- oidc_cache_crypto_openssl_error(r, "EVP_EncryptFinal_ex");
- return -1;
- }
- ciphertext_len += len;
-
- /* get the tag */
- if (!EVP_CIPHER_CTX_ctrl(ctx, OIDC_CACHE_CRYPTO_GET_TAG, tag_len,
- (void *) tag)) {
- oidc_cache_crypto_openssl_error(r, "EVP_CIPHER_CTX_ctrl");
- return -1;
- }
-
- /* clean up */
- EVP_CIPHER_CTX_free(ctx);
-
- return ciphertext_len;
-}
-
-/*
- * AES GCM decrypt
- */
-static int oidc_cache_crypto_decrypt_impl(request_rec *r,
- unsigned char *ciphertext, int ciphertext_len, const unsigned
char *aad,
- int aad_len, const unsigned char *tag, int tag_len, unsigned
char *key,
- const unsigned char *iv, int iv_len, unsigned char *plaintext) {
- EVP_CIPHER_CTX *ctx;
- int len;
- int plaintext_len;
- int ret;
-
- /* create and initialize the context */
- if (!(ctx = EVP_CIPHER_CTX_new())) {
- oidc_cache_crypto_openssl_error(r, "EVP_CIPHER_CTX_new");
- return -1;
- }
-
- /* initialize the decryption cipher */
- if (!EVP_DecryptInit_ex(ctx, OIDC_CACHE_CIPHER, NULL, NULL, NULL)) {
- oidc_cache_crypto_openssl_error(r, "EVP_DecryptInit_ex");
- return -1;
- }
-
- /* set IV length */
- if (!EVP_CIPHER_CTX_ctrl(ctx, OIDC_CACHE_CRYPTO_SET_IVLEN, iv_len,
NULL)) {
- oidc_cache_crypto_openssl_error(r, "EVP_CIPHER_CTX_ctrl");
- return -1;
- }
-
- /* initialize key and IV */
- if (!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) {
- oidc_cache_crypto_openssl_error(r, "EVP_DecryptInit_ex");
- return -1;
- }
-
- /* provide AAD data */
- if (!EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len)) {
- oidc_cache_crypto_openssl_error(r, "EVP_DecryptUpdate aad:
aad_len=%d",
- aad_len);
- return -1;
- }
-
- /* provide the message to be decrypted and obtain the plaintext output
*/
- if (!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext,
ciphertext_len)) {
- oidc_cache_crypto_openssl_error(r, "EVP_DecryptUpdate
ciphertext");
- return -1;
- }
- plaintext_len = len;
-
- /* set expected tag value; works in OpenSSL 1.0.1d and later */
- if (!EVP_CIPHER_CTX_ctrl(ctx, OIDC_CACHE_CRYPTO_SET_TAG, tag_len,
- (void *) tag)) {
- oidc_cache_crypto_openssl_error(r, "EVP_CIPHER_CTX_ctrl");
- return -1;
- }
-
- /*
- * finalize the decryption; a positive return value indicates success,
- * anything else is a failure - the plaintext is not trustworthy
- */
- ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
-
- /* clean up */
- EVP_CIPHER_CTX_free(ctx);
-
- if (ret > 0) {
- /* success */
- plaintext_len += len;
- return plaintext_len;
- } else {
- /* verify failed */
- oidc_cache_crypto_openssl_error(r, "EVP_DecryptFinal_ex");
- return -1;
- }
-}
-
-/*
- * static AAD value for encryption/decryption
- */
-static const unsigned char OIDC_CACHE_CRYPTO_GCM_AAD[] = { 0x4d, 0x23, 0xc3,
- 0xce, 0xc3, 0x34, 0xb4, 0x9b, 0xdb, 0x37, 0x0c, 0x43, 0x7f,
0xec, 0x78,
- 0xde };
+#define OIDC_CACHE_CRYPTO_JSON_KEY "c"
/*
- * static IV value for encryption/decryption
+ * AES GCM encrypt using the crypto passphrase as symmetric key
*/
-static const unsigned char OIDC_CACHE_CRYPTO_GCM_IV[] = { 0x00, 0x01, 0x02,
- 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
0x0d, 0x0e,
- 0x0f };
+static apr_byte_t oidc_cache_crypto_encrypt(request_rec *r, const char
*plaintext, const char *key,
+ char **result) {
+ apr_byte_t rv = FALSE;
+ json_t *json = NULL;
-/*
- * AES GCM encrypt using the static AAD and IV
- */
-static int oidc_cache_crypto_encrypt(request_rec *r, const char *plaintext,
- unsigned char *key, char **result) {
- char *encoded = NULL, *p = NULL, *e_tag = NULL;
- unsigned char *ciphertext = NULL;
- int plaintext_len, ciphertext_len, encoded_len, e_tag_len;
- unsigned char tag[OIDC_CACHE_TAG_LEN];
-
- /* allocate space for the ciphertext */
- plaintext_len = strlen(plaintext) + 1;
- ciphertext = apr_pcalloc(r->pool,
- (plaintext_len +
EVP_CIPHER_block_size(OIDC_CACHE_CIPHER)));
-
- ciphertext_len = oidc_cache_crypto_encrypt_impl(r,
- (unsigned char *) plaintext, plaintext_len,
- OIDC_CACHE_CRYPTO_GCM_AAD,
sizeof(OIDC_CACHE_CRYPTO_GCM_AAD), key,
- OIDC_CACHE_CRYPTO_GCM_IV,
sizeof(OIDC_CACHE_CRYPTO_GCM_IV),
- ciphertext, tag, sizeof(tag));
-
- /* base64url encode the resulting ciphertext */
- encoded_len = oidc_base64url_encode(r, &encoded, (const char *)
ciphertext,
- ciphertext_len, 1);
- if (encoded_len > 0) {
- p = encoded;
-
- /* base64url encode the tag */
- e_tag_len = oidc_base64url_encode(r, &e_tag, (const char *) tag,
- OIDC_CACHE_TAG_LEN, 1);
-
- /* now allocated space for the concatenated base64url encoded
ciphertext and tag */
- encoded = apr_pcalloc(r->pool, encoded_len + 1 + e_tag_len + 1);
- memcpy(encoded, p, encoded_len);
- p = encoded + encoded_len;
- *p = OIDC_CHAR_DOT;
- p++;
-
- /* append the tag in the buffer */
- memcpy(p, e_tag, e_tag_len);
- encoded_len += e_tag_len + 1;
+ json = json_object();
+ json_object_set_new(json, OIDC_CACHE_CRYPTO_JSON_KEY,
json_string(plaintext));
- /* make sure the result is \0 terminated */
- encoded[encoded_len] = '\0';
+ rv = oidc_util_jwt_create(r, (const char*) key, json, result, TRUE);
- *result = encoded;
- }
+ if (json)
+ json_decref(json);
- return encoded_len;
+ return rv;
}
/*
- * AES GCM decrypt using the static AAD and IV
+ * AES GCM decrypt using the crypto passphrase as symmetric key
*/
-static int oidc_cache_crypto_decrypt(request_rec *r, const char *cache_value,
- unsigned char *key, unsigned char **plaintext) {
+static apr_byte_t oidc_cache_crypto_decrypt(request_rec *r, const char
*cache_value,
+ const char *key, char **plaintext) {
- int len = -1;
+ apr_byte_t rv = FALSE;
+ json_t *json = NULL;
- /* grab the base64url-encoded tag after the "." */
- char *encoded_tag = strstr(cache_value, ".");
- if (encoded_tag == NULL) {
- oidc_error(r,
- "corrupted cache value: no tag separator found
in encrypted value");
- return FALSE;
- }
+ rv = oidc_util_jwt_verify(r, (const char*) key, cache_value, &json,
TRUE);
+ if (rv == FALSE)
+ goto end;
- /* make sure we don't modify the original string since it may be just a
pointer into the cache (shm) */
- cache_value = apr_pstrmemdup(r->pool, cache_value,
- strlen(cache_value) - strlen(encoded_tag));
- encoded_tag++;
-
- /* base64url decode the ciphertext */
- char *d_bytes = NULL;
- int d_len = oidc_base64url_decode(r->pool, &d_bytes, cache_value);
-
- /* base64url decode the tag */
- char *t_bytes = NULL;
- int t_len = oidc_base64url_decode(r->pool, &t_bytes, encoded_tag);
-
- /* see if we're still good to go */
- if ((d_len > 0) && (t_len > 0)) {
-
- /* allocated space for the plaintext */
- *plaintext = apr_pcalloc(r->pool,
- (d_len +
EVP_CIPHER_block_size(OIDC_CACHE_CIPHER) - 1));
-
- /* decrypt the ciphertext providing the tag value */
-
- len = oidc_cache_crypto_decrypt_impl(r, (unsigned char *)
d_bytes,
- d_len, OIDC_CACHE_CRYPTO_GCM_AAD,
- sizeof(OIDC_CACHE_CRYPTO_GCM_AAD), (unsigned
char *) t_bytes,
- t_len, key, OIDC_CACHE_CRYPTO_GCM_IV,
- sizeof(OIDC_CACHE_CRYPTO_GCM_IV), *plaintext);
-
- /* check the result and make sure it is \0 terminated */
- if (len > -1) {
- (*plaintext)[len] = '\0';
- } else {
- *plaintext = NULL;
- }
+ rv = oidc_json_object_get_string(r->pool, json,
OIDC_CACHE_CRYPTO_JSON_KEY, plaintext, NULL);
- }
+end:
- return len;
-}
+ if (json)
+ json_decref(json);
-/*
- * hash the crypto passhphrase so it has enough key length for AES GCM 256
- */
-static unsigned char *oidc_cache_hash_passphrase(request_rec *r,
- const char *passphrase) {
-
- unsigned char *key = NULL;
- unsigned int key_len = 0;
- oidc_jose_error_t err;
-
- if (oidc_jose_hash_bytes(r->pool, OIDC_JOSE_ALG_SHA256,
- (const unsigned char *) passphrase, strlen(passphrase),
&key,
- &key_len, &err) == FALSE) {
- oidc_error(r, "oidc_jose_hash_bytes returned an error: %s",
err.text);
- return NULL;
- }
-
- return key;
+ return rv;
}
/*
* hash a cache key and a crypto passphrase so the result is suitable as an
randomized cache key
*/
-static char *oidc_cache_get_hashed_key(request_rec *r, const char *passphrase,
- const char *key) {
+static char* oidc_cache_get_hashed_key(request_rec *r, const char *passphrase,
const char *key) {
char *input = apr_psprintf(r->pool, "%s:%s", passphrase, key);
char *output = NULL;
- if (oidc_util_hash_string_and_base64url_encode(r, OIDC_JOSE_ALG_SHA256,
- input, &output) == FALSE) {
- oidc_error(r,
- "oidc_util_hash_string_and_base64url_encode
returned an error");
+ if (oidc_util_hash_string_and_base64url_encode(r, OIDC_JOSE_ALG_SHA256,
input, &output)
+ == FALSE) {
+ oidc_error(r, "oidc_util_hash_string_and_base64url_encode
returned an error");
return NULL;
}
return output;
@@ -604,9 +338,7 @@
goto out;
}
- rc = (oidc_cache_crypto_decrypt(r, cache_value,
- oidc_cache_hash_passphrase(r, cfg->crypto_passphrase),
- (unsigned char **) value) > 0);
+ rc = oidc_cache_crypto_decrypt(r, cache_value, cfg->crypto_passphrase,
value);
out:
/* log the result */
@@ -650,9 +382,7 @@
goto out;
if (value != NULL) {
- if (oidc_cache_crypto_encrypt(r, value,
- oidc_cache_hash_passphrase(r,
cfg->crypto_passphrase),
- &encoded) <= 0)
+ if (oidc_cache_crypto_encrypt(r, value,
cfg->crypto_passphrase, &encoded) == FALSE)
goto out;
value = encoded;
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/mod_auth_openidc-2.4.8.2/src/cache/redis.c
new/mod_auth_openidc-2.4.9/src/cache/redis.c
--- old/mod_auth_openidc-2.4.8.2/src/cache/redis.c 2021-05-13
09:30:00.000000000 +0200
+++ new/mod_auth_openidc-2.4.9/src/cache/redis.c 2021-07-22
18:30:06.000000000 +0200
@@ -265,10 +265,12 @@
* execute Redis command and deal with return value
*/
static redisReply* oidc_cache_redis_command(request_rec *r,
- oidc_cache_cfg_redis_t *context, const char *command) {
+ oidc_cache_cfg_redis_t *context, const char *format, ...) {
redisReply *reply = NULL;
int i = 0;
+ va_list ap;
+ va_start(ap, format);
/* try to execute a command at max 2 times while reconnecting */
for (i = 0; i < OIDC_REDIS_MAX_TRIES; i++) {
@@ -278,7 +280,7 @@
break;
/* execute the actual command */
- reply = redisCommand(context->ctx, command);
+ reply = redisvCommand(context->ctx, format, ap);
/* check for errors, need to return error replies for cache
miss case REDIS_REPLY_NIL */
if ((reply != NULL) && (reply->type != REDIS_REPLY_ERROR))
@@ -298,6 +300,8 @@
oidc_cache_redis_free(context);
}
+ va_end(ap);
+
return reply;
}
@@ -318,9 +322,8 @@
return FALSE;
/* get */
- reply = oidc_cache_redis_command(r, context,
- apr_psprintf(r->pool, "GET %s",
- oidc_cache_redis_get_key(r->pool,
section, key)));
+ reply =
+ oidc_cache_redis_command(r, context, "GET %s",
oidc_cache_redis_get_key(r->pool, section, key));
if (reply == NULL)
goto end;
@@ -384,9 +387,8 @@
if (value == NULL) {
/* delete it */
- reply = oidc_cache_redis_command(r, context,
- apr_psprintf(r->pool, "DEL %s",
-
oidc_cache_redis_get_key(r->pool, section, key)));
+ reply =
+ oidc_cache_redis_command(r, context, "DEL %s",
oidc_cache_redis_get_key(r->pool, section, key));
} else {
@@ -394,10 +396,8 @@
timeout = apr_time_sec(expiry - apr_time_now());
/* store it */
- reply = oidc_cache_redis_command(r, context,
- apr_psprintf(r->pool, "SETEX %s %d %s",
-
oidc_cache_redis_get_key(r->pool, section, key),
- timeout, value));
+ reply =
+ oidc_cache_redis_command(r, context, "SETEX %s
%d %s", oidc_cache_redis_get_key(r->pool, section, key), timeout, value);
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/mod_auth_openidc-2.4.8.2/src/mod_auth_openidc.c
new/mod_auth_openidc-2.4.9/src/mod_auth_openidc.c
--- old/mod_auth_openidc-2.4.8.2/src/mod_auth_openidc.c 2021-05-07
23:27:25.000000000 +0200
+++ new/mod_auth_openidc-2.4.9/src/mod_auth_openidc.c 2021-07-22
18:30:06.000000000 +0200
@@ -468,7 +468,7 @@
" </script>\n", jmethod, json,
location ?
apr_psprintf(r->pool,
"window.location='%s';\n",
-
location) :
+
oidc_util_javascript_escape(r->pool, location)) :
"");
if (location == NULL) {
if (javascript_method)
@@ -513,10 +513,10 @@
" input.type = \"hidden\";\n"
"
document.forms[0].appendChild(input);\n"
" }\n"
- " document.forms[0].action =
'%s';\n"
+ " document.forms[0].action =
\"%s\";\n"
" document.forms[0].submit();\n"
" }\n"
- " </script>\n", method,
original_url);
+ " </script>\n", method,
oidc_util_javascript_escape(r->pool, original_url));
const char *body = " <p>Restoring...</p>\n"
" <form method=\"post\"></form>\n";
@@ -688,16 +688,16 @@
/* check that the timestamp is not beyond the valid interval */
if (apr_time_now() > ts + apr_time_from_sec(c->state_timeout)) {
oidc_error(r, "state has expired");
- /*
- * note that this overrides redirection to the OIDCDefaultURL
as done later...
- * see:
https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/mod_auth_openidc/L4JFBw-XCNU/BWi2Fmk2AwAJ
- */
- oidc_util_html_send_error(r, c->error_template,
- "Invalid Authentication Response",
- apr_psprintf(r->pool,
- "This is due to a timeout;
please restart your authentication session by re-entering the URL/bookmark you
originally wanted to access: %s",
-
oidc_proto_state_get_original_url(*proto_state)),
- OK);
+ if ((c->default_sso_url == NULL)
+ || (apr_table_get(r->subprocess_env,
"OIDC_NO_DEFAULT_URL_ON_STATE_TIMEOUT") != NULL)) {
+ oidc_util_html_send_error(r, c->error_template,
"Invalid Authentication Response", apr_psprintf(r->pool, "This is due to a
timeout; please restart your authentication session by re-entering the
URL/bookmark you originally wanted to access: %s",
oidc_proto_state_get_original_url(*proto_state)),
+ OK);
+ /*
+ * a hack for Apache 2.4 to prevent it from writing its
own 500/400/302 HTML document
+ * text by making ap_send_error_response in
http_protocol.c return early...
+ */
+ r->header_only = 1;
+ }
oidc_proto_state_destroy(*proto_state);
return FALSE;
}
@@ -992,7 +992,7 @@
/* get the issuer value from the session state */
const char *issuer = oidc_session_get_issuer(r, session);
if (issuer == NULL) {
- oidc_error(r, "session corrupted: no issuer found in session");
+ oidc_warn(r, "empty or invalid session: no issuer found");
return FALSE;
}
@@ -1553,7 +1553,7 @@
char *java_script = apr_psprintf(r->pool,
" <script type=\"text/javascript\">\n"
" window.top.location.href =
'%s?session=logout';\n"
- " </script>\n", oidc_get_redirect_uri(r, c));
+ " </script>\n", oidc_util_javascript_escape(r->pool,
oidc_get_redirect_uri(r, c)));
return oidc_util_html_send(r, "Redirecting...", java_script, NULL, NULL,
OK);
@@ -1912,6 +1912,7 @@
"invalid authorization response state;
a default SSO URL is set, sending the user there: %s",
c->default_sso_url);
oidc_util_hdr_out_location_set(r, c->default_sso_url);
+ //oidc_util_hdr_err_out_add(r, "Location",
c->default_sso_url));
return HTTP_MOVED_TEMPORARILY;
}
oidc_error(r,
@@ -2251,8 +2252,17 @@
if (provider == NULL) {
// TODO: should we use an explicit redirect to the discovery
endpoint (maybe a "discovery" param to the redirect_uri)?
- if (c->metadata_dir != NULL)
- return oidc_discovery(r, c);
+ if (c->metadata_dir != NULL) {
+ /*
+ * Will be handled in the content handler; avoid:
+ * No authentication done but request not allowed
without authentication
+ * by setting r->user
+ */
+ oidc_debug(r, "defer discovery to the content handler");
+ oidc_request_state_set(r,
OIDC_REQUEST_STATE_KEY_DISCOVERY, "");
+ r->user = "";
+ return OK;
+ }
/* we're not using multiple OP's configured in a metadata
directory, pick the statically configured OP */
if (oidc_provider_static_config(r, c, &provider) == FALSE)
@@ -2620,8 +2630,8 @@
// TODO: use oauth.ssl_validate_server ...
token = oidc_session_get_refresh_token(r, session);
if (token != NULL) {
- apr_table_addn(params, "token_type_hint", "refresh_token");
- apr_table_addn(params, "token", token);
+ apr_table_setn(params, OIDC_PROTO_TOKEN_TYPE_HINT,
OIDC_PROTO_REFRESH_TOKEN);
+ apr_table_setn(params, OIDC_PROTO_TOKEN, token);
if (oidc_util_http_post_form(r,
provider->revocation_endpoint_url,
params, basic_auth, bearer_auth,
c->oauth.ssl_validate_server,
@@ -2630,13 +2640,14 @@
NULL, NULL) == FALSE) {
oidc_warn(r, "revoking refresh token failed");
}
- apr_table_clear(params);
+ apr_table_unset(params, OIDC_PROTO_TOKEN_TYPE_HINT);
+ apr_table_unset(params, OIDC_PROTO_TOKEN);
}
token = oidc_session_get_access_token(r, session);
if (token != NULL) {
- apr_table_addn(params, "token_type_hint", "access_token");
- apr_table_addn(params, "token", token);
+ apr_table_setn(params, OIDC_PROTO_TOKEN_TYPE_HINT,
OIDC_PROTO_ACCESS_TOKEN);
+ apr_table_setn(params, OIDC_PROTO_TOKEN, token);
if (oidc_util_http_post_form(r,
provider->revocation_endpoint_url,
params, basic_auth, bearer_auth,
c->oauth.ssl_validate_server,
@@ -2686,16 +2697,14 @@
const char *accept = oidc_util_hdr_in_accept_get(r);
if ((apr_strnatcmp(url, OIDC_IMG_STYLE_LOGOUT_PARAM_VALUE) == 0)
|| ((accept) && strstr(accept,
OIDC_CONTENT_TYPE_IMAGE_PNG))) {
- // terminate with DONE instead of OK
- // to avoid Apache returning auth/authz error 401 for
the redirect URI
return oidc_util_http_send(r, (const char*)
&oidc_transparent_pixel,
sizeof(oidc_transparent_pixel),
OIDC_CONTENT_TYPE_IMAGE_PNG,
- DONE);
+ OK);
}
/* standard HTTP based logout: should be called in an iframe
from the OP */
return oidc_util_html_send(r, "Logged Out", NULL, NULL,
- "<p>Logged Out</p>", DONE);
+ "<p>Logged Out</p>", OK);
}
/* see if we don't need to go somewhere special after killing the
session locally */
@@ -2751,6 +2760,11 @@
goto out;
}
+ if ((jwt->header.alg == NULL) || (strcmp(jwt->header.alg, "none") ==
0)) {
+ oidc_error(r, "logout token is not signed");
+ goto out;
+ }
+
provider = oidc_get_provider_for_issuer(r, cfg, jwt->payload.iss,
FALSE);
if (provider == NULL) {
oidc_error(r, "no provider found for issuer: %s",
jwt->payload.iss);
@@ -2864,12 +2878,12 @@
sid = oidc_make_sid_iss_unique(r, sid, provider->issuer);
oidc_cache_get_sid(r, sid, &uuid);
if (uuid == NULL) {
- oidc_error(r,
- "could not find session based on sid/sub
provided in logout token: %s",
+ // this may happen when we are the caller
+ oidc_warn(r,
+ "could not (or no longer) find a session based
on sid/sub provided in logout token: %s",
sid);
- // return HTTP 200 according to (new?) spec and terminate early
- // to avoid Apache returning auth/authz error 500 for the
redirect URI
- rc = DONE;
+ r->user = "";
+ rc = OK;
goto out;
}
@@ -2884,9 +2898,8 @@
oidc_cache_set_sid(r, sid, NULL, 0);
oidc_cache_set_session(r, uuid, NULL, 0);
- // terminate with DONE instead of OK
- // to avoid Apache returning auth/authz error 500 for the redirect URI
- rc = DONE;
+ r->user = "";
+ rc = OK;
out:
@@ -2907,12 +2920,21 @@
return rc;
}
+#define OIDC_MAX_URL_LENGTH DEFAULT_LIMIT_REQUEST_LINE * 2
+
static apr_byte_t oidc_validate_redirect_url(request_rec *r, oidc_cfg *c,
- const char *url, apr_byte_t restrict_to_host, char **err_str,
+ const char *redirect_to_url, apr_byte_t restrict_to_host, char
**err_str,
char **err_desc) {
apr_uri_t uri;
const char *c_host = NULL;
apr_hash_index_t *hi = NULL;
+ size_t i = 0;
+ char *url = apr_pstrndup(r->pool, redirect_to_url, OIDC_MAX_URL_LENGTH);
+
+ // replace potentially harmful backslashes with forward slashes
+ for (i = 0; i < strlen(url); i++)
+ if (url[i] == '\\')
+ url[i] = '/';
if (apr_uri_parse(r->pool, url, &uri) != APR_SUCCESS) {
*err_str = apr_pstrdup(r->pool, "Malformed URL");
@@ -3051,6 +3073,9 @@
OIDC_STR_QUERY,
oidc_util_escape_string(r, url));
}
+ //char *state = NULL;
+ //oidc_proto_generate_nonce(r, &state, 8);
+ //url = apr_psprintf(r->pool, "%s&state=%s", logout_request,
state);
url = logout_request;
}
@@ -3706,7 +3731,7 @@
// oidc_util_get_request_parameter(r,
"error_description", &descr);
//
// /* send user facing error to browser */
- // return oidc_util_html_send_error(r, error,
descr, DONE);
+ // return oidc_util_html_send_error(r, error,
descr, OK);
return oidc_handle_redirect_authorization_response(r, c,
session);
}
@@ -4136,27 +4161,43 @@
apr_byte_t needs_save = FALSE;
oidc_session_t *session = NULL;
- if (oidc_enabled(r)
- && oidc_util_request_matches_url(r,
oidc_get_redirect_uri(r, c))) {
+ if (oidc_enabled(r) == TRUE) {
+
+ if (oidc_util_request_matches_url(r, oidc_get_redirect_uri(r,
c)) == TRUE) {
+
+ if (oidc_util_request_has_parameter(r,
+ OIDC_REDIRECT_URI_REQUEST_INFO)) {
+
+ oidc_session_load(r, &session);
+
+ rc = oidc_handle_existing_session(r, c,
session, &needs_save);
+ if (rc == OK)
+ /* handle request for session info */
+ rc = oidc_handle_info_request(r, c,
session, needs_save);
+
+ /* free resources allocated for the session */
+ oidc_session_free(r, session);
+
+ } else if (oidc_util_request_has_parameter(r,
+ OIDC_REDIRECT_URI_REQUEST_JWKS)) {
+
+ /* handle JWKs request */
+ rc = oidc_handle_jwks(r, c);
- if (oidc_util_request_has_parameter(r,
- OIDC_REDIRECT_URI_REQUEST_INFO)) {
+ } else {
+
+ rc = OK;
+
+ }
- oidc_session_load(r, &session);
+ } else if (oidc_request_state_get(r,
OIDC_REQUEST_STATE_KEY_DISCOVERY) != NULL) {
- rc = oidc_handle_existing_session(r, c, session,
&needs_save);
- if (rc == OK)
- /* handle request for session info */
- rc = oidc_handle_info_request(r, c, session,
needs_save);
+ rc = oidc_discovery(r, c);
- /* free resources allocated for the session */
- oidc_session_free(r, session);
+ } else if (oidc_request_state_get(r,
OIDC_REQUEST_STATE_KEY_AUTHN) != NULL) {
- } else if (oidc_util_request_has_parameter(r,
- OIDC_REDIRECT_URI_REQUEST_JWKS)) {
+ rc = OK;
- /* handle JWKs request */
- rc = oidc_handle_jwks(r, c);
}
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/mod_auth_openidc-2.4.8.2/src/mod_auth_openidc.h
new/mod_auth_openidc-2.4.9/src/mod_auth_openidc.h
--- old/mod_auth_openidc-2.4.8.2/src/mod_auth_openidc.h 2021-05-13
09:30:00.000000000 +0200
+++ new/mod_auth_openidc-2.4.9/src/mod_auth_openidc.h 2021-07-22
18:30:00.000000000 +0200
@@ -87,6 +87,8 @@
/* keys for storing info in the request state */
#define OIDC_REQUEST_STATE_KEY_IDTOKEN "i"
#define OIDC_REQUEST_STATE_KEY_CLAIMS "c"
+#define OIDC_REQUEST_STATE_KEY_DISCOVERY "d"
+#define OIDC_REQUEST_STATE_KEY_AUTHN "a"
/* parameter name of the callback URL in the discovery response */
#define OIDC_DISC_CB_PARAM "oidc_callback"
@@ -478,6 +480,8 @@
#define OIDC_PROTO_SCOPE "scope"
#define OIDC_PROTO_REFRESH_TOKEN "refresh_token"
#define OIDC_PROTO_TOKEN_TYPE "token_type"
+#define OIDC_PROTO_TOKEN_TYPE_HINT "token_type_hint"
+#define OIDC_PROTO_TOKEN "token"
#define OIDC_PROTO_EXPIRES_IN "expires_in"
#define OIDC_PROTO_RESPONSE_TYPE "response_type"
#define OIDC_PROTO_RESPONSE_MODE "response_mode"
@@ -776,6 +780,7 @@
apr_byte_t oidc_json_object_get_int(apr_pool_t *pool, json_t *json, const char
*name, int *value, const int default_value);
apr_byte_t oidc_json_object_get_bool(apr_pool_t *pool, json_t *json, const
char *name, int *value, const int default_value);
char *oidc_util_html_escape(apr_pool_t *pool, const char *input);
+char *oidc_util_javascript_escape(apr_pool_t *pool, const char *input);
void oidc_util_table_add_query_encoded_params(apr_pool_t *pool, apr_table_t
*table, const char *params);
apr_hash_t * oidc_util_merge_key_sets(apr_pool_t *pool, apr_hash_t *k1, const
apr_array_header_t *k2);
apr_hash_t * oidc_util_merge_key_sets_hash(apr_pool_t *pool, apr_hash_t *k1,
apr_hash_t *k2);
@@ -784,8 +789,8 @@
apr_byte_t oidc_util_json_merge(request_rec *r, json_t *src, json_t *dst);
int oidc_util_cookie_domain_valid(const char *hostname, char *cookie_domain);
apr_byte_t oidc_util_hash_string_and_base64url_encode(request_rec *r, const
char *openssl_hash_algo, const char *input, char **output);
-apr_byte_t oidc_util_jwt_create(request_rec *r, const char *secret, json_t
*payload, char **compact_encoded_jwt);
-apr_byte_t oidc_util_jwt_verify(request_rec *r, const char *secret, const char
*compact_encoded_jwt, json_t **result);
+apr_byte_t oidc_util_jwt_create(request_rec *r, const char *secret, json_t
*payload, char **compact_encoded_jwt, apr_byte_t strip_header);
+apr_byte_t oidc_util_jwt_verify(request_rec *r, const char *secret, const char
*compact_encoded_jwt, json_t **result, apr_byte_t stripped_header);
char *oidc_util_get_chunked_cookie(request_rec *r, const char *cookieName, int
cookie_chunk_size);
void oidc_util_set_chunked_cookie(request_rec *r, const char *cookieName,
const char *cookieValue, apr_time_t expires, int chunkSize, const char *ext);
apr_byte_t oidc_util_create_symmetric_key(request_rec *r, const char
*client_secret, unsigned int r_key_len, const char *hash_algo, apr_byte_t
set_kid, oidc_jwk_t **jwk);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/mod_auth_openidc-2.4.8.2/src/proto.c
new/mod_auth_openidc-2.4.9/src/proto.c
--- old/mod_auth_openidc-2.4.8.2/src/proto.c 2021-05-07 23:27:25.000000000
+0200
+++ new/mod_auth_openidc-2.4.9/src/proto.c 2021-07-22 18:30:00.000000000
+0200
@@ -758,7 +758,16 @@
/* and tell Apache to return an HTTP Redirect (302)
message */
rv = HTTP_MOVED_TEMPORARILY;
+
+ } else {
+
+ /* signal this to the content handler */
+ oidc_request_state_set(r, OIDC_REQUEST_STATE_KEY_AUTHN,
"");
+ r->user = "";
+ rv = OK;
+
}
+
} else {
oidc_error(r, "provider->auth_request_method set to wrong
value: %d",
provider->auth_request_method);
@@ -962,16 +971,16 @@
oidc_proto_state_t* oidc_proto_state_from_cookie(request_rec *r, oidc_cfg *c,
const char *cookieValue) {
json_t *result = NULL;
- oidc_util_jwt_verify(r, c->crypto_passphrase, cookieValue, &result);
+ oidc_util_jwt_verify(r, c->crypto_passphrase, cookieValue, &result,
TRUE);
return result;
}
-char* oidc_proto_state_to_cookie(request_rec *r, oidc_cfg *c,
- oidc_proto_state_t *proto_state) {
+char* oidc_proto_state_to_cookie(request_rec *r, oidc_cfg *c,
oidc_proto_state_t *proto_state) {
char *cookieValue = NULL;
- oidc_util_jwt_create(r, c->crypto_passphrase, proto_state,
&cookieValue);
+ oidc_util_jwt_create(r, c->crypto_passphrase, proto_state,
&cookieValue, TRUE);
return cookieValue;
}
+
char* oidc_proto_state_to_string(request_rec *r,
oidc_proto_state_t *proto_state) {
return oidc_util_encode_json_object(r, proto_state, JSON_COMPACT);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/mod_auth_openidc-2.4.8.2/src/session.c
new/mod_auth_openidc-2.4.9/src/session.c
--- old/mod_auth_openidc-2.4.8.2/src/session.c 2021-05-11 17:51:42.000000000
+0200
+++ new/mod_auth_openidc-2.4.9/src/session.c 2021-07-22 18:30:00.000000000
+0200
@@ -66,32 +66,29 @@
/* the name of the sid attribute in the session */
#define OIDC_SESSION_SID_KEY "sid"
-static apr_byte_t oidc_session_encode(request_rec *r, oidc_cfg *c,
- oidc_session_t *z, char **s_value, apr_byte_t encrypt) {
+static apr_byte_t oidc_session_encode(request_rec *r, oidc_cfg *c,
oidc_session_t *z,
+ char **s_value, apr_byte_t encrypt) {
if (encrypt == FALSE) {
*s_value = oidc_util_encode_json_object(r, z->state,
JSON_COMPACT);
return (*s_value != NULL);
}
- if (oidc_util_jwt_create(r, c->crypto_passphrase, z->state,
- s_value) == FALSE)
+ if (oidc_util_jwt_create(r, c->crypto_passphrase, z->state, s_value,
TRUE) == FALSE)
return FALSE;
return TRUE;
}
-static apr_byte_t oidc_session_decode(request_rec *r, oidc_cfg *c,
- oidc_session_t *z, const char *s_json, apr_byte_t encrypt) {
+static apr_byte_t oidc_session_decode(request_rec *r, oidc_cfg *c,
oidc_session_t *z,
+ const char *s_json, apr_byte_t encrypt) {
if (encrypt == FALSE) {
return oidc_util_decode_json_object(r, s_json, &z->state);
}
- if (oidc_util_jwt_verify(r, c->crypto_passphrase, s_json,
- &z->state) == FALSE) {
- oidc_error(r,
- "could not verify secure JWT: cache value
possibly corrupted");
+ if (oidc_util_jwt_verify(r, c->crypto_passphrase, s_json, &z->state,
TRUE) == FALSE) {
+ oidc_error(r, "could not verify secure JWT: cache value
possibly corrupted");
return FALSE;
}
return TRUE;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/mod_auth_openidc-2.4.8.2/src/util.c
new/mod_auth_openidc-2.4.9/src/util.c
--- old/mod_auth_openidc-2.4.8.2/src/util.c 2021-05-07 23:27:25.000000000
+0200
+++ new/mod_auth_openidc-2.4.9/src/util.c 2021-07-22 18:30:00.000000000
+0200
@@ -132,8 +132,10 @@
return apr_base64_decode(*dst, dec);
}
-apr_byte_t oidc_util_jwt_create(request_rec *r, const char *secret,
- json_t *payload, char **compact_encoded_jwt) {
+#define OIDC_JWT_HDR_DIR_A256GCM
"eyJhbGciOiAiZGlyIiwgImVuYyI6ICJBMjU2R0NNIn0.."
+
+apr_byte_t oidc_util_jwt_create(request_rec *r, const char *secret, json_t
*payload,
+ char **compact_encoded_jwt, apr_byte_t strip_header) {
apr_byte_t rv = FALSE;
oidc_jose_error_t err;
@@ -142,8 +144,7 @@
oidc_jwt_t *jwt = NULL;
oidc_jwt_t *jwe = NULL;
- if (oidc_util_create_symmetric_key(r, secret, 0, OIDC_JOSE_ALG_SHA256,
- FALSE, &jwk) == FALSE)
+ if (oidc_util_create_symmetric_key(r, secret, 0, OIDC_JOSE_ALG_SHA256,
FALSE, &jwk) == FALSE)
goto end;
jwt = oidc_jwt_new(r->pool, TRUE, FALSE);
@@ -170,12 +171,14 @@
jwe->header.enc = apr_pstrdup(r->pool, CJOSE_HDR_ENC_A256GCM);
const char *cser = oidc_jwt_serialize(r->pool, jwt, &err);
- if (oidc_jwt_encrypt(r->pool, jwe, jwk, cser, compact_encoded_jwt, &err)
- == FALSE) {
+ if (oidc_jwt_encrypt(r->pool, jwe, jwk, cser, compact_encoded_jwt,
&err) == FALSE) {
oidc_error(r, "encrypting JWT failed: %s",
oidc_jose_e2s(r->pool, err));
goto end;
}
+ if (strip_header == TRUE)
+ *compact_encoded_jwt += strlen(OIDC_JWT_HDR_DIR_A256GCM);
+
rv = TRUE;
end:
@@ -192,11 +195,10 @@
return rv;
}
-apr_byte_t oidc_util_jwt_verify(request_rec *r, const char *secret,
- const char *compact_encoded_jwt, json_t **result) {
+apr_byte_t oidc_util_jwt_verify(request_rec *r, const char *secret, const char
*compact_encoded_jwt,
+ json_t **result, apr_byte_t stripped_header) {
- oidc_debug(r, "enter: JWT header=%s",
- oidc_proto_peek_jwt_header(r, compact_encoded_jwt,
NULL));
+ oidc_debug(r, "enter: JWT header=%s", oidc_proto_peek_jwt_header(r,
compact_encoded_jwt, NULL));
apr_byte_t rv = FALSE;
oidc_jose_error_t err;
@@ -204,15 +206,17 @@
oidc_jwk_t *jwk = NULL;
oidc_jwt_t *jwt = NULL;
- if (oidc_util_create_symmetric_key(r, secret, 0, OIDC_JOSE_ALG_SHA256,
- FALSE, &jwk) == FALSE)
+ if (oidc_util_create_symmetric_key(r, secret, 0, OIDC_JOSE_ALG_SHA256,
FALSE, &jwk) == FALSE)
goto end;
apr_hash_t *keys = apr_hash_make(r->pool);
apr_hash_set(keys, "", APR_HASH_KEY_STRING, jwk);
- if (oidc_jwt_parse(r->pool, compact_encoded_jwt, &jwt, keys, &err)
- == FALSE) {
+ if (stripped_header == TRUE)
+ compact_encoded_jwt =
+ apr_pstrcat(r->pool, OIDC_JWT_HDR_DIR_A256GCM,
compact_encoded_jwt, NULL);
+
+ if (oidc_jwt_parse(r->pool, compact_encoded_jwt, &jwt, keys, &err) ==
FALSE) {
oidc_error(r, "parsing JWT failed: %s", oidc_jose_e2s(r->pool,
err));
goto end;
}
@@ -363,6 +367,87 @@
}
/*
+ * JavaScript escape a string
+ */
+char* oidc_util_javascript_escape(apr_pool_t *pool, const char *s) {
+ const char *cp;
+ char *output;
+ size_t outputlen;
+ int i;
+
+ if (s == NULL) {
+ return NULL;
+ }
+
+ outputlen = 0;
+ for (cp = s; *cp; cp++) {
+ switch (*cp) {
+ case '\'':
+ case '"':
+ case '\\':
+ case '/':
+ case 0x0D:
+ case 0x0A:
+ outputlen += 2;
+ break;
+ case '<':
+ case '>':
+ outputlen += 4;
+ break;
+ default:
+ outputlen += 1;
+ break;
+ }
+ }
+
+ i = 0;
+ output = apr_palloc(pool, outputlen + 1);
+ for (cp = s; *cp; cp++) {
+ switch (*cp) {
+ case '\'':
+ (void)strcpy(&output[i], "\\'");
+ i += 2;
+ break;
+ case '"':
+ (void)strcpy(&output[i], "\\\"");
+ i += 2;
+ break;
+ case '\\':
+ (void)strcpy(&output[i], "\\\\");
+ i += 2;
+ break;
+ case '/':
+ (void)strcpy(&output[i], "\\/");
+ i += 2;
+ break;
+ case 0x0D:
+ (void)strcpy(&output[i], "\\r");
+ i += 2;
+ break;
+ case 0x0A:
+ (void)strcpy(&output[i], "\\n");
+ i += 2;
+ break;
+ case '<':
+ (void)strcpy(&output[i], "\\x3c");
+ i += 4;
+ break;
+ case '>':
+ (void)strcpy(&output[i], "\\x3e");
+ i += 4;
+ break;
+ default:
+ output[i] = *cp;
+ i += 1;
+ break;
+ }
+ }
+ output[i] = '\0';
+ return output;
+}
+
+
+/*
* get the URL scheme that is currently being accessed
*/
static const char* oidc_get_current_url_scheme(const request_rec *r) {
@@ -388,6 +473,27 @@
}
/*
+ * get the Port part that is currently being accessed
+ */
+static const char* oidc_get_port_from_host( const char *host_hdr){
+ char *p = NULL;
+ char *i = NULL;
+
+ if (host_hdr) {
+ if (host_hdr[0]=='[') {
+ i = strchr(host_hdr, ']');
+ p = strchr(i, OIDC_CHAR_COLON);
+ } else {
+ p = strchr(host_hdr, OIDC_CHAR_COLON);
+ }
+ }
+ if (p)
+ return p;
+ else
+ return NULL;
+}
+
+/*
* get the URL port that is currently being accessed
*/
static const char* oidc_get_current_url_port(const request_rec *r,
@@ -407,7 +513,7 @@
*/
const char *host_hdr = oidc_util_hdr_in_x_forwarded_host_get(r);
if (host_hdr) {
- port_str = strchr(host_hdr, OIDC_CHAR_COLON);
+ port_str = oidc_get_port_from_host(host_hdr);
if (port_str)
port_str++;
return port_str;
@@ -419,7 +525,7 @@
*/
host_hdr = oidc_util_hdr_in_host_get(r);
if (host_hdr) {
- port_str = strchr(host_hdr, OIDC_CHAR_COLON);
+ port_str = oidc_get_port_from_host(host_hdr);
if (port_str) {
port_str++;
return port_str;
@@ -452,13 +558,22 @@
*/
const char* oidc_get_current_url_host(request_rec *r) {
const char *host_str = oidc_util_hdr_in_x_forwarded_host_get(r);
+ char *p = NULL;
+ char *i = NULL;
if (host_str == NULL)
host_str = oidc_util_hdr_in_host_get(r);
if (host_str) {
host_str = apr_pstrdup(r->pool, host_str);
- char *p = strchr(host_str, OIDC_CHAR_COLON);
- if (p != NULL)
- *p = '\0';
+
+ if (host_str[0] == '[') {
+ i= strchr(host_str, ']');
+ p = strchr(i, OIDC_CHAR_COLON);
+ } else {
+ p = strchr(host_str, OIDC_CHAR_COLON);
+ }
+
+ if (p != NULL)
+ *p = '\0';
} else {
/* no Host header, HTTP 1.0 */
host_str = ap_get_server_name(r);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/mod_auth_openidc-2.4.8.2/test/test.c
new/mod_auth_openidc-2.4.9/test/test.c
--- old/mod_auth_openidc-2.4.8.2/test/test.c 2021-05-07 16:06:34.000000000
+0200
+++ new/mod_auth_openidc-2.4.9/test/test.c 2021-07-22 18:30:00.000000000
+0200
@@ -1285,6 +1285,16 @@
TST_ASSERT_STR("test_current_url (8)", url,
"http://remotehost:8380/private/?foo=bar¶m1=value1");
+ apr_table_set(r->headers_in, "Host",
"[fd04:41b1:1170:28:16b0:446b:9fb7:7118]:8380");
+ url = oidc_get_current_url(r);
+ TST_ASSERT_STR("test_current_url (9)", url,
+
"http://[fd04:41b1:1170:28:16b0:446b:9fb7:7118]:8380/private/?foo=bar¶m1=value1");
+
+ apr_table_set(r->headers_in, "Host",
"[fd04:41b1:1170:28:16b0:446b:9fb7:7118]");
+ url = oidc_get_current_url(r);
+ TST_ASSERT_STR("test_current_url (10)", url,
+
"http://[fd04:41b1:1170:28:16b0:446b:9fb7:7118]/private/?foo=bar¶m1=value1");
+
return 0;
}