This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/10.1.x by this push:
     new f1203ae0b5 Fix BZ 68348 - add support for the cookie attribute 
partitioned
f1203ae0b5 is described below

commit f1203ae0b5a136fc4ce5a8749a59542af7787716
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Jan 4 12:52:17 2024 +0000

    Fix BZ 68348 - add support for the cookie attribute partitioned
    
    https://bz.apache.org/bugzilla/show_bug.cgi?id=68348
---
 java/org/apache/catalina/Context.java              | 27 +++++++++++++++++
 .../catalina/authenticator/AuthenticatorBase.java  |  7 +++--
 .../apache/catalina/authenticator/Constants.java   |  9 ++++++
 .../catalina/authenticator/SingleSignOn.java       |  9 ++++--
 .../core/ApplicationSessionCookieConfig.java       |  3 ++
 java/org/apache/catalina/core/StandardContext.java | 16 ++++++++++
 .../org/apache/catalina/startup/FailedContext.java |  5 ++++
 .../tomcat/util/descriptor/web/Constants.java      |  7 +++++
 .../tomcat/util/http/CookieProcessorBase.java      | 34 ++++++++++++++++++++++
 .../tomcat/util/http/Rfc6265CookieProcessor.java   | 13 +++++++++
 test/org/apache/tomcat/unittest/TesterContext.java | 10 +++++++
 .../util/http/TestCookieProcessorGeneration.java   | 30 +++++++++++++++++++
 webapps/docs/changelog.xml                         |  4 +++
 webapps/docs/config/context.xml                    |  7 +++++
 14 files changed, 176 insertions(+), 5 deletions(-)

diff --git a/java/org/apache/catalina/Context.java 
b/java/org/apache/catalina/Context.java
index f9ebfe3340..fb50454dcc 100644
--- a/java/org/apache/catalina/Context.java
+++ b/java/org/apache/catalina/Context.java
@@ -264,6 +264,33 @@ public interface Context extends Container, ContextBind {
     void setUseHttpOnly(boolean useHttpOnly);
 
 
+    /**
+     * Should the {@code Partitioned} attribute be added to session cookies 
created for this web application.
+     * <p>
+     * The name of the attribute used to indicate a partitioned cookie as part 
of
+     * <a 
href="https://developers.google.com/privacy-sandbox/3pcd#partitioned";>CHIPS</a> 
is not defined by an RFC and
+     * may change in a non-backwards compatible way once equivalent 
functionality is included in an RFC.
+     *
+     * @return {@code true} if the {@code Partitioned} attribute should be 
added to session cookies created for this web
+     *             application, otherwise {@code false}
+     */
+    boolean getUsePartitioned();
+
+
+    /**
+     * Configure whether the {@code Partitioned} attribute should be added to 
session cookies created for this web
+     * application.
+     * <p>
+     * The name of the attribute used to indicate a partitioned cookie as part 
of
+     * <a 
href="https://developers.google.com/privacy-sandbox/3pcd#partitioned";>CHIPS</a> 
is not defined by an RFC and
+     * may change in a non-backwards compatible way once equivalent 
functionality is included in an RFC.
+     *
+     * @param usePartitioned {@code true} if the {@code Partitioned} attribute 
should be added to session cookies
+     *                           created for this web application, otherwise 
{@code false}
+     */
+    void setUsePartitioned(boolean usePartitioned);
+
+
     /**
      * Gets the domain to use for session cookies. Overrides any setting that
      * may be specified by the application.
diff --git a/java/org/apache/catalina/authenticator/AuthenticatorBase.java 
b/java/org/apache/catalina/authenticator/AuthenticatorBase.java
index 352f984c79..9a558d9c05 100644
--- a/java/org/apache/catalina/authenticator/AuthenticatorBase.java
+++ b/java/org/apache/catalina/authenticator/AuthenticatorBase.java
@@ -1078,13 +1078,16 @@ public abstract class AuthenticatorBase extends 
ValveBase implements Authenticat
                 cookie.setDomain(ssoDomain);
             }
 
-            // Configure httpOnly on SSO cookie using same rules as session
-            // cookies
+            // Configure httpOnly on SSO cookie using same rules as session 
cookies
             if 
(request.getServletContext().getSessionCookieConfig().isHttpOnly() ||
                     request.getContext().getUseHttpOnly()) {
                 cookie.setHttpOnly(true);
             }
 
+            // Configure Partitioned on SSO cookie using same rules as session 
cookies
+            cookie.setAttribute(Constants.COOKIE_PARTITIONED_ATTR,
+                    
Boolean.toString(request.getContext().getUsePartitioned()));
+
             response.addCookie(cookie);
 
             // Register this principal with our SSO valve
diff --git a/java/org/apache/catalina/authenticator/Constants.java 
b/java/org/apache/catalina/authenticator/Constants.java
index 6b0778da79..5485782d5c 100644
--- a/java/org/apache/catalina/authenticator/Constants.java
+++ b/java/org/apache/catalina/authenticator/Constants.java
@@ -37,6 +37,15 @@ public class Constants {
     // Cookie name for single sign on support
     public static final String SINGLE_SIGN_ON_COOKIE = "JSESSIONIDSSO";
 
+    /**
+     * The name of the attribute used to indicate a partitioned cookie as part 
of
+     * <a 
href="https://developers.google.com/privacy-sandbox/3pcd#partitioned";>CHIPS</a>.
 This cookie attribute is not
+     * defined by an RFC and may change in a non-backwards compatible way once 
equivalent functionality is included in
+     * an RFC.
+     */
+    public static final String COOKIE_PARTITIONED_ATTR =
+            
org.apache.tomcat.util.descriptor.web.Constants.COOKIE_PARTITIONED_ATTR;
+
 
     // --------------------------------------------------------- Request Notes
 
diff --git a/java/org/apache/catalina/authenticator/SingleSignOn.java 
b/java/org/apache/catalina/authenticator/SingleSignOn.java
index 4d302ab40b..c8f9d53c4a 100644
--- a/java/org/apache/catalina/authenticator/SingleSignOn.java
+++ b/java/org/apache/catalina/authenticator/SingleSignOn.java
@@ -273,14 +273,17 @@ public class SingleSignOn extends ValveBase {
             if (domain != null) {
                 cookie.setDomain(domain);
             }
-            // This is going to trigger a Set-Cookie header. While the value is
-            // not security sensitive, ensure that expectations for secure and
-            // httpOnly are met
+            /*
+             * This is going to trigger a Set-Cookie header. While the value 
is not security sensitive, ensure that
+             * expectations for secure, httpOnly and Partitioned are met.
+             */
             cookie.setSecure(request.isSecure());
             if 
(request.getServletContext().getSessionCookieConfig().isHttpOnly() ||
                     request.getContext().getUseHttpOnly()) {
                 cookie.setHttpOnly(true);
             }
+            cookie.setAttribute(Constants.COOKIE_PARTITIONED_ATTR,
+                    
Boolean.toString(request.getContext().getUsePartitioned()));
 
             response.addCookie(cookie);
         }
diff --git a/java/org/apache/catalina/core/ApplicationSessionCookieConfig.java 
b/java/org/apache/catalina/core/ApplicationSessionCookieConfig.java
index c9f6bda066..97a001b95f 100644
--- a/java/org/apache/catalina/core/ApplicationSessionCookieConfig.java
+++ b/java/org/apache/catalina/core/ApplicationSessionCookieConfig.java
@@ -221,6 +221,9 @@ public class ApplicationSessionCookieConfig implements 
SessionCookieConfig {
             cookie.setHttpOnly(true);
         }
 
+        cookie.setAttribute(Constants.COOKIE_PARTITIONED_ATTR,
+                Boolean.toString(context.getUsePartitioned()));
+
         cookie.setPath(SessionConfig.getSessionCookiePath(context));
 
         // Other attributes
diff --git a/java/org/apache/catalina/core/StandardContext.java 
b/java/org/apache/catalina/core/StandardContext.java
index e4a701872b..1eb87b2f36 100644
--- a/java/org/apache/catalina/core/StandardContext.java
+++ b/java/org/apache/catalina/core/StandardContext.java
@@ -638,6 +638,8 @@ public class StandardContext extends ContainerBase 
implements Context, Notificat
      */
     private boolean useHttpOnly = true;
 
+    private boolean usePartitioned = false;
+
 
     /**
      * The domain to use for session cookies. <code>null</code> indicates that 
the domain is controlled by the
@@ -1568,6 +1570,20 @@ public class StandardContext extends ContainerBase 
implements Context, Notificat
     }
 
 
+    @Override
+    public boolean getUsePartitioned() {
+        return usePartitioned;
+    }
+
+
+    @Override
+    public void setUsePartitioned(boolean usePartitioned) {
+        boolean oldUsePartitioned = this.usePartitioned;
+        this.usePartitioned = usePartitioned;
+        support.firePropertyChange("usePartitioned", oldUsePartitioned, 
this.usePartitioned);
+    }
+
+
     /**
      * Gets the domain to use for session cookies. Overrides any setting that 
may be specified by the application.
      *
diff --git a/java/org/apache/catalina/startup/FailedContext.java 
b/java/org/apache/catalina/startup/FailedContext.java
index e352ce28c7..7bbfdfcfb0 100644
--- a/java/org/apache/catalina/startup/FailedContext.java
+++ b/java/org/apache/catalina/startup/FailedContext.java
@@ -345,6 +345,11 @@ public class FailedContext extends LifecycleMBeanBase 
implements Context {
     @Override
     public void setUseHttpOnly(boolean useHttpOnly) { /* NO-OP */ }
 
+    @Override
+    public boolean getUsePartitioned() { return false; }
+    @Override
+    public void setUsePartitioned(boolean usePartitioned) { /* NO-OP */ }
+
     @Override
     public String getSessionCookieDomain() { return null; }
     @Override
diff --git a/java/org/apache/tomcat/util/descriptor/web/Constants.java 
b/java/org/apache/tomcat/util/descriptor/web/Constants.java
index 7b6228c638..fabf7b4baf 100644
--- a/java/org/apache/tomcat/util/descriptor/web/Constants.java
+++ b/java/org/apache/tomcat/util/descriptor/web/Constants.java
@@ -31,4 +31,11 @@ public class Constants {
     public static final String COOKIE_SECURE_ATTR = "Secure";
     public static final String COOKIE_HTTP_ONLY_ATTR = "HttpOnly";
     public static final String COOKIE_SAME_SITE_ATTR = "SameSite";
+    /**
+     * The name of the attribute used to indicate a partitioned cookie as part 
of
+     * <a 
href="https://developers.google.com/privacy-sandbox/3pcd#partitioned";>CHIPS</a>.
 This cookie attribute is not
+     * defined by an RFC and may change in a non-backwards compatible way once 
equivalent functionality is included in
+     * an RFC.
+     */
+    public static final String COOKIE_PARTITIONED_ATTR = "Partitioned";
 }
diff --git a/java/org/apache/tomcat/util/http/CookieProcessorBase.java 
b/java/org/apache/tomcat/util/http/CookieProcessorBase.java
index 00c852cc75..5815ca4cd4 100644
--- a/java/org/apache/tomcat/util/http/CookieProcessorBase.java
+++ b/java/org/apache/tomcat/util/http/CookieProcessorBase.java
@@ -40,6 +40,9 @@ public abstract class CookieProcessorBase implements 
CookieProcessor {
 
     private SameSiteCookies sameSiteCookies = SameSiteCookies.UNSET;
 
+    private boolean partitioned = false;
+
+
     public SameSiteCookies getSameSiteCookies() {
         return sameSiteCookies;
     }
@@ -47,4 +50,35 @@ public abstract class CookieProcessorBase implements 
CookieProcessor {
     public void setSameSiteCookies(String sameSiteCookies) {
         this.sameSiteCookies = SameSiteCookies.fromString(sameSiteCookies);
     }
+
+
+    /**
+     * Should the {@code Partitioned} attribute be added by default to cookies 
created for this web application.
+     * <p>
+     * The name of the attribute used to indicate a partitioned cookie as part 
of
+     * <a 
href="https://developers.google.com/privacy-sandbox/3pcd#partitioned";>CHIPS</a> 
is not defined by an RFC and
+     * may change in a non-backwards compatible way once equivalent 
functionality is included in an RFC.
+     *
+     * @return {@code true} if the {@code Partitioned} attribute should be 
added by default to cookies created for this
+     *             web application, otherwise {@code false}
+     */
+    public boolean getPartitioned() {
+        return partitioned;
+    }
+
+
+    /**
+     * Configure whether the {@code Partitioned} attribute should be added by 
default to cookies created for this web
+     * application.
+     * <p>
+     * The name of the attribute used to indicate a partitioned cookie as part 
of
+     * <a 
href="https://developers.google.com/privacy-sandbox/3pcd#partitioned";>CHIPS</a> 
is not defined by an RFC and
+     * may change in a non-backwards compatible way once equivalent 
functionality is included in an RFC.
+     *
+     * @param partitioned {@code true} if the {@code Partitioned} attribute 
should be added by default to cookies
+     *                        created for this web application, otherwise 
{@code false}
+     */
+    public void setPartitioned(boolean partitioned) {
+        this.partitioned = partitioned;
+    }
 }
diff --git a/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java 
b/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java
index fc4e5cbe8a..d41fa281f7 100644
--- a/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java
+++ b/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java
@@ -177,6 +177,18 @@ public class Rfc6265CookieProcessor extends 
CookieProcessorBase {
             header.append(cookieSameSite);
         }
 
+        String cookiePartitioned = 
cookie.getAttribute(Constants.COOKIE_PARTITIONED_ATTR);
+        if (cookiePartitioned == null) {
+            if (getPartitioned()) {
+                header.append("; Partitioned");
+            }
+        } else {
+            if (Boolean.parseBoolean(cookiePartitioned)) {
+                header.append("; Partitioned");
+            }
+        }
+
+
         // Add the remaining attributes
         for (Map.Entry<String,String> entry : 
cookie.getAttributes().entrySet()) {
             switch (entry.getKey()) {
@@ -187,6 +199,7 @@ public class Rfc6265CookieProcessor extends 
CookieProcessorBase {
                 case Constants.COOKIE_SECURE_ATTR:
                 case Constants.COOKIE_HTTP_ONLY_ATTR:
                 case Constants.COOKIE_SAME_SITE_ATTR:
+                case Constants.COOKIE_PARTITIONED_ATTR:
                     // Handled above so NO-OP
                     break;
                 default: {
diff --git a/test/org/apache/tomcat/unittest/TesterContext.java 
b/test/org/apache/tomcat/unittest/TesterContext.java
index b0c624b951..1b980556cd 100644
--- a/test/org/apache/tomcat/unittest/TesterContext.java
+++ b/test/org/apache/tomcat/unittest/TesterContext.java
@@ -415,6 +415,16 @@ public class TesterContext implements Context {
         // NO-OP
     }
 
+    @Override
+    public boolean getUsePartitioned() {
+        return false;
+    }
+
+    @Override
+    public void setUsePartitioned(boolean usePartitioned) {
+        // NO-OP
+    }
+
     @Override
     public String getSessionCookieDomain() {
         return null;
diff --git 
a/test/org/apache/tomcat/util/http/TestCookieProcessorGeneration.java 
b/test/org/apache/tomcat/util/http/TestCookieProcessorGeneration.java
index b74a851a16..43ac4d0ffd 100644
--- a/test/org/apache/tomcat/util/http/TestCookieProcessorGeneration.java
+++ b/test/org/apache/tomcat/util/http/TestCookieProcessorGeneration.java
@@ -209,6 +209,36 @@ public class TestCookieProcessorGeneration {
         Assert.assertEquals("foo=bar; Secure; HttpOnly; SameSite=Strict", 
rfc6265.generateHeader(cookie, null));
     }
 
+
+    @Test
+    public void testPartitionedCookies() {
+        Rfc6265CookieProcessor rfc6265 = new Rfc6265CookieProcessor();
+
+        Cookie cookie = new Cookie("foo", "bar");
+
+        Assert.assertEquals("foo=bar", rfc6265.generateHeader(cookie, null));
+
+        rfc6265.setPartitioned(false);
+
+        Assert.assertEquals("foo=bar", rfc6265.generateHeader(cookie, null));
+
+        rfc6265.setPartitioned(true);
+
+        Assert.assertEquals("foo=bar; Partitioned", 
rfc6265.generateHeader(cookie, null));
+
+        cookie.setSecure(true);
+        cookie.setHttpOnly(true);
+
+        rfc6265.setPartitioned(false);
+
+        Assert.assertEquals("foo=bar; Secure; HttpOnly", 
rfc6265.generateHeader(cookie, null));
+
+        rfc6265.setPartitioned(true);
+
+        Assert.assertEquals("foo=bar; Secure; HttpOnly; Partitioned", 
rfc6265.generateHeader(cookie, null));
+    }
+
+
     private void doTest(Cookie cookie, String expectedRfc6265) {
         CookieProcessor rfc6265 = new Rfc6265CookieProcessor();
         doTest(cookie, rfc6265, expectedRfc6265);
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 558e4bd850..a5d1ee50bc 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -139,6 +139,10 @@
         used in the request line, if any, to make the check case insensitive
         since host names are case insensitive. (markt)
       </fix>
+      <add>
+        <bug>68348</bug>: Add support for the partitioned attribute for cookies
+        including session cookies. (markt)
+      </add>
     </changelog>
   </subsection>
   <subsection name="Web Applications">
diff --git a/webapps/docs/config/context.xml b/webapps/docs/config/context.xml
index e804c8c240..c233df716f 100644
--- a/webapps/docs/config/context.xml
+++ b/webapps/docs/config/context.xml
@@ -654,6 +654,13 @@
           <code>true</code>.</p>
       </attribute>
 
+      <attribute name="usePartitioned" required="false">
+       <p>Should the Partitioned flag be set on session cookies? Defaults to 
<code>false</code>.</p>
+       <p>Note: The name of the attribute used to indicate a partitioned 
cookie as part of
+       <a 
href="https://developers.google.com/privacy-sandbox/3pcd#partitioned";>CHIPS</a> 
is not defined by an RFC and
+       may change in a non-backwards compatible way once equivalent 
functionality is included in an RFC.</p>
+      </attribute>
+
       <attribute name="useRelativeRedirects" required="false">
         <p>Controls whether HTTP 1.1 and later location headers generated by a
         call to


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to