Blame SOURCES/0019-add-SameSite-attribute-on-cookie-clearance-logout.patch

5b8408
From b68ac577b465f54e7eb38e48a65e5cf4c88c74c5 Mon Sep 17 00:00:00 2001
5b8408
From: Hans Zandbelt <hans.zandbelt@zmartzone.eu>
5b8408
Date: Thu, 3 Sep 2020 16:52:30 +0200
5b8408
Subject: [PATCH 19/19] add SameSite attribute on cookie clearance / logout
5b8408
5b8408
bump to 2.4.4.1; thanks @v0gler
5b8408
5b8408
Signed-off-by: Hans Zandbelt <hans.zandbelt@zmartzone.eu>
5b8408
(cherry picked from commit 314000d179c2d08af6897725f37980e1f0891aa6)
5b8408
---
5b8408
 ChangeLog              |  4 ++++
5b8408
 src/mod_auth_openidc.c | 42 +++++++++++++++++++++++-------------------
5b8408
 src/mod_auth_openidc.h |  5 +++++
5b8408
 src/session.c          | 16 +++++++++-------
5b8408
 4 files changed, 41 insertions(+), 26 deletions(-)
5b8408
5b8408
diff --git a/ChangeLog b/ChangeLog
5b8408
index 3db7110..eba2ebc 100644
5b8408
--- a/ChangeLog
5b8408
+++ b/ChangeLog
5b8408
@@ -1,3 +1,7 @@
5b8408
+09/03/2020
5b8408
+- add SameSite attribute on cookie clearance / logout; thanks @v0gler
5b8408
+- bump to 2.4.4.1
5b8408
+
5b8408
 02/03/2020
5b8408
 - fix: also add SameSite=None to by-value session cookies
5b8408
 - bump to 2.4.2rc0
5b8408
diff --git a/src/mod_auth_openidc.c b/src/mod_auth_openidc.c
5b8408
index 0d2b37c..68fa2ce 100644
5b8408
--- a/src/mod_auth_openidc.c
5b8408
+++ b/src/mod_auth_openidc.c
5b8408
@@ -717,7 +717,8 @@ static int oidc_delete_oldest_state_cookies(request_rec *r,
5b8408
 		oidc_warn(r,
5b8408
 				"deleting oldest state cookie: %s (time until expiry " APR_TIME_T_FMT " seconds)",
5b8408
 				oldest->name, apr_time_sec(oldest->timestamp - apr_time_now()));
5b8408
-		oidc_util_set_cookie(r, oldest->name, "", 0, NULL);
5b8408
+		oidc_util_set_cookie(r, oldest->name, "", 0,
5b8408
+				OIDC_COOKIE_EXT_SAME_SITE_NONE);
5b8408
 		if (prev_oldest)
5b8408
 			prev_oldest->next = oldest->next;
5b8408
 		else
5b8408
@@ -762,7 +763,7 @@ static int oidc_clean_expired_state_cookies(request_rec *r, oidc_cfg *c,
5b8408
 								oidc_error(r, "state (%s) has expired",
5b8408
 										cookieName);
5b8408
 								oidc_util_set_cookie(r, cookieName, "", 0,
5b8408
-										NULL);
5b8408
+										OIDC_COOKIE_EXT_SAME_SITE_NONE);
5b8408
 							} else {
5b8408
 								if (first == NULL) {
5b8408
 									first = apr_pcalloc(r->pool,
5b8408
@@ -779,6 +780,12 @@ static int oidc_clean_expired_state_cookies(request_rec *r, oidc_cfg *c,
5b8408
 								number_of_valid_state_cookies++;
5b8408
 							}
5b8408
 							oidc_proto_state_destroy(proto_state);
5b8408
+						} else {
5b8408
+							oidc_warn(r,
5b8408
+									"state cookie could not be retrieved/decoded, deleting: %s",
5b8408
+									cookieName);
5b8408
+							oidc_util_set_cookie(r, cookieName, "", 0,
5b8408
+									OIDC_COOKIE_EXT_SAME_SITE_NONE);
5b8408
 						}
5b8408
 					}
5b8408
 				}
5b8408
@@ -816,7 +823,7 @@ static apr_byte_t oidc_restore_proto_state(request_rec *r, oidc_cfg *c,
5b8408
 	}
5b8408
 
5b8408
 	/* clear state cookie because we don't need it anymore */
5b8408
-	oidc_util_set_cookie(r, cookieName, "", 0, NULL);
5b8408
+	oidc_util_set_cookie(r, cookieName, "", 0, OIDC_COOKIE_EXT_SAME_SITE_NONE);
5b8408
 
5b8408
 	*proto_state = oidc_proto_state_from_cookie(r, c, cookieValue);
5b8408
 	if (*proto_state == NULL)
5b8408
@@ -916,9 +923,7 @@ static int oidc_authorization_request_set_cookie(request_rec *r, oidc_cfg *c,
5b8408
 
5b8408
 	/* set it as a cookie */
5b8408
 	oidc_util_set_cookie(r, cookieName, cookieValue, -1,
5b8408
-			c->cookie_same_site ?
5b8408
-					OIDC_COOKIE_EXT_SAME_SITE_LAX :
5b8408
-					OIDC_COOKIE_EXT_SAME_SITE_NONE);
5b8408
+			OIDC_COOKIE_SAMESITE_LAX(c));
5b8408
 
5b8408
 	return HTTP_OK;
5b8408
 }
5b8408
@@ -2183,9 +2188,7 @@ static int oidc_discovery(request_rec *r, oidc_cfg *cfg) {
5b8408
 
5b8408
 		/* set CSRF cookie */
5b8408
 		oidc_util_set_cookie(r, OIDC_CSRF_NAME, csrf, -1,
5b8408
-				cfg->cookie_same_site ?
5b8408
-						OIDC_COOKIE_EXT_SAME_SITE_STRICT :
5b8408
-						OIDC_COOKIE_EXT_SAME_SITE_NONE);
5b8408
+				OIDC_COOKIE_SAMESITE_STRICT(cfg));
5b8408
 
5b8408
 		/* see if we need to preserve POST parameters through Javascript/HTML5 storage */
5b8408
 		if (oidc_post_preserve_javascript(r, url, NULL, NULL) == TRUE)
5b8408
@@ -2278,9 +2281,7 @@ static int oidc_discovery(request_rec *r, oidc_cfg *cfg) {
5b8408
 	s = apr_psprintf(r->pool, "%s</form>\n", s);
5b8408
 
5b8408
 	oidc_util_set_cookie(r, OIDC_CSRF_NAME, csrf, -1,
5b8408
-			cfg->cookie_same_site ?
5b8408
-					OIDC_COOKIE_EXT_SAME_SITE_STRICT :
5b8408
-					OIDC_COOKIE_EXT_SAME_SITE_NONE);
5b8408
+			OIDC_COOKIE_SAMESITE_STRICT(cfg));
5b8408
 
5b8408
 	char *javascript = NULL, *javascript_method = NULL;
5b8408
 	char *html_head =
5b8408
@@ -2501,7 +2502,8 @@ static int oidc_handle_discovery_response(request_rec *r, oidc_cfg *c) {
5b8408
 	if (csrf_cookie) {
5b8408
 
5b8408
 		/* clean CSRF cookie */
5b8408
-		oidc_util_set_cookie(r, OIDC_CSRF_NAME, "", 0, NULL);
5b8408
+		oidc_util_set_cookie(r, OIDC_CSRF_NAME, "", 0,
5b8408
+				OIDC_COOKIE_EXT_SAME_SITE_NONE);
5b8408
 
5b8408
 		/* compare CSRF cookie value with query parameter value */
5b8408
 		if ((csrf_query == NULL)
5b8408
@@ -2639,12 +2641,12 @@ static int oidc_handle_logout_request(request_rec *r, oidc_cfg *c,
5b8408
 
5b8408
 	oidc_debug(r, "enter (url=%s)", url);
5b8408
 
5b8408
-	/* if there's no remote_user then there's no (stored) session to kill */
5b8408
-	if (session->remote_user != NULL) {
5b8408
-
5b8408
-		/* remove session state (cq. cache entry and cookie) */
5b8408
-		oidc_session_kill(r, session);
5b8408
-	}
5b8408
+	/*
5b8408
+	 * remove session state (cq. cache entry and cookie)
5b8408
+	 * always clear the session cookie because the cookie may be not sent (but still in the browser)
5b8408
+	 * due to SameSite policies
5b8408
+	 */
5b8408
+	oidc_session_kill(r, session);
5b8408
 
5b8408
 	/* see if this is the OP calling us */
5b8408
 	if (oidc_is_front_channel_logout(url)) {
5b8408
@@ -2661,6 +2663,8 @@ static int oidc_handle_logout_request(request_rec *r, oidc_cfg *c,
5b8408
 		const char *accept = oidc_util_hdr_in_accept_get(r);
5b8408
 		if ((apr_strnatcmp(url, OIDC_IMG_STYLE_LOGOUT_PARAM_VALUE) == 0)
5b8408
 				|| ((accept) && strstr(accept, OIDC_CONTENT_TYPE_IMAGE_PNG))) {
5b8408
+			// terminate with DONE instead of OK
5b8408
+			// to avoid Apache returning auth/authz error 401 for the redirect URI
5b8408
 			return oidc_util_http_send(r,
5b8408
 					(const char *) &oidc_transparent_pixel,
5b8408
 					sizeof(oidc_transparent_pixel), OIDC_CONTENT_TYPE_IMAGE_PNG,
5b8408
diff --git a/src/mod_auth_openidc.h b/src/mod_auth_openidc.h
5b8408
index 5f1a79a..6821d0c 100644
5b8408
--- a/src/mod_auth_openidc.h
5b8408
+++ b/src/mod_auth_openidc.h
5b8408
@@ -215,6 +215,11 @@ APLOG_USE_MODULE(auth_openidc);
5b8408
 #define OIDC_COOKIE_EXT_SAME_SITE_STRICT "SameSite=Strict"
5b8408
 #define OIDC_COOKIE_EXT_SAME_SITE_NONE   "SameSite=None"
5b8408
 
5b8408
+#define OIDC_COOKIE_SAMESITE_STRICT(c) \
5b8408
+	c->cookie_same_site ? OIDC_COOKIE_EXT_SAME_SITE_STRICT : OIDC_COOKIE_EXT_SAME_SITE_NONE
5b8408
+#define OIDC_COOKIE_SAMESITE_LAX(c) \
5b8408
+	c->cookie_same_site ? OIDC_COOKIE_EXT_SAME_SITE_LAX : OIDC_COOKIE_EXT_SAME_SITE_NONE
5b8408
+
5b8408
 /* https://tools.ietf.org/html/draft-ietf-tokbind-ttrp-01 */
5b8408
 #define OIDC_TB_CFG_PROVIDED_ENV_VAR     "Sec-Provided-Token-Binding-ID"
5b8408
 
5b8408
diff --git a/src/session.c b/src/session.c
5b8408
index e7194bd..539ea21 100644
5b8408
--- a/src/session.c
5b8408
+++ b/src/session.c
5b8408
@@ -155,7 +155,7 @@ static apr_byte_t oidc_session_load_cache(request_rec *r, oidc_session_t *z) {
5b8408
 
5b8408
 					/* delete the session cookie */
5b8408
 					oidc_util_set_cookie(r, oidc_cfg_dir_cookie(r), "", 0,
5b8408
-							NULL);
5b8408
+					                OIDC_COOKIE_EXT_SAME_SITE_NONE);
5b8408
 					/* delete the cache entry */
5b8408
 					rc = oidc_cache_set_session(r, z->uuid, NULL, 0);
5b8408
 					/* clear the session */
5b8408
@@ -208,7 +208,8 @@ static apr_byte_t oidc_session_save_cache(request_rec *r, oidc_session_t *z,
5b8408
 
5b8408
 	} else {
5b8408
 		/* clear the cookie */
5b8408
-		oidc_util_set_cookie(r, oidc_cfg_dir_cookie(r), "", 0, NULL);
5b8408
+		oidc_util_set_cookie(r, oidc_cfg_dir_cookie(r), "", 0,
5b8408
+				OIDC_COOKIE_EXT_SAME_SITE_NONE);
5b8408
 
5b8408
 		/* remove the session from the cache */
5b8408
 		rc = oidc_cache_set_session(r, z->uuid, NULL, 0);
5b8408
@@ -245,11 +246,12 @@ static apr_byte_t oidc_session_save_cookie(request_rec *r, oidc_session_t *z,
5b8408
 	oidc_util_set_chunked_cookie(r, oidc_cfg_dir_cookie(r), cookieValue,
5b8408
 			c->persistent_session_cookie ? z->expiry : -1,
5b8408
 					c->session_cookie_chunk_size,
5b8408
-					c->cookie_same_site ?
5b8408
-							(first_time ?
5b8408
-									OIDC_COOKIE_EXT_SAME_SITE_LAX :
5b8408
-									OIDC_COOKIE_EXT_SAME_SITE_STRICT) :
5b8408
-									OIDC_COOKIE_EXT_SAME_SITE_NONE);
5b8408
+					(z->state == NULL) ? OIDC_COOKIE_EXT_SAME_SITE_NONE :
5b8408
+							c->cookie_same_site ?
5b8408
+									(first_time ?
5b8408
+											OIDC_COOKIE_EXT_SAME_SITE_LAX :
5b8408
+											OIDC_COOKIE_EXT_SAME_SITE_STRICT) :
5b8408
+											OIDC_COOKIE_EXT_SAME_SITE_NONE);
5b8408
 
5b8408
 	return TRUE;
5b8408
 }
5b8408
-- 
5b8408
2.26.2
5b8408