[cpp-xmltooling] branch master updated: SSPCPP-878 - SameSite workaround using second cookie

Scott Cantor cantor.2 at osu.edu
Tue Feb 11 12:56:48 EST 2020


This is an automated email from the git hooks/post-receive script.

scantor pushed a commit to branch master
in repository cpp-xmltooling.

View the commit online:
http://git.shibboleth.net/view/?p=cpp-xmltooling.git;a=commit;h=d26cff814719ca86937b34c9e0b5c900c852b855

The following commit(s) were added to refs/heads/master by this push:
       new  d26cff8   SSPCPP-878 - SameSite workaround using second cookie
d26cff8 is described below

commit d26cff814719ca86937b34c9e0b5c900c852b855
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Feb 11 12:55:10 2020 -0500

    SSPCPP-878 - SameSite workaround using second cookie
    
    https://issues.shibboleth.net/jira/browse/SSPCPP-878
    
    Redesign of APIs to allow refactor of SP cookie code.
---
 xmltooling/io/HTTPRequest.cpp  |  5 +++++
 xmltooling/io/HTTPRequest.h    | 10 +++++++++-
 xmltooling/io/HTTPResponse.cpp | 44 ++++++++++++++++++++++++++++++++----------
 xmltooling/io/HTTPResponse.h   | 39 ++++++++++++++++++++++++++++---------
 4 files changed, 78 insertions(+), 20 deletions(-)

diff --git a/xmltooling/io/HTTPRequest.cpp b/xmltooling/io/HTTPRequest.cpp
index 3d47b47..d0edd55 100644
--- a/xmltooling/io/HTTPRequest.cpp
+++ b/xmltooling/io/HTTPRequest.cpp
@@ -239,6 +239,11 @@ const map<string,string>& HTTPRequest::getCookies() const
     return m_cookieMap;
 }
 
+const char* HTTPRequest::getCookie(const char* name) const
+{
+    return getCookie(name, false);
+}
+
 const char* HTTPRequest::getCookie(const char* name, bool sameSiteFallback) const
 {
     map<string,string>::const_iterator lookup = getCookies().find(name);
diff --git a/xmltooling/io/HTTPRequest.h b/xmltooling/io/HTTPRequest.h
index 064850d..7170ec9 100644
--- a/xmltooling/io/HTTPRequest.h
+++ b/xmltooling/io/HTTPRequest.h
@@ -94,6 +94,14 @@ namespace xmltooling {
         virtual std::string getHeader(const char* name) const=0;
 
         /**
+        * Get a cookie value supplied by the client.
+        * 
+        * @param name  name of cookie
+        * @return  cookie value or nullptr
+        */
+        virtual const char* getCookie(const char* name) const;
+
+        /**
          * Get a cookie value supplied by the client.
          *
          * The boolean flag enables the workaround for older clients with
@@ -104,7 +112,7 @@ namespace xmltooling {
          * @param sameSiteFallback enables lookaside to fallback cookie name
          * @return  cookie value or nullptr
          */
-        virtual const char* getCookie(const char* name, bool sameSiteFallback=false) const;
+        virtual const char* getCookie(const char* name, bool sameSiteFallback) const;
 
         /**
          * Gets all the cookies supplied by the client.
diff --git a/xmltooling/io/HTTPResponse.cpp b/xmltooling/io/HTTPResponse.cpp
index 3af2301..29515d3 100644
--- a/xmltooling/io/HTTPResponse.cpp
+++ b/xmltooling/io/HTTPResponse.cpp
@@ -86,34 +86,58 @@ void HTTPResponse::setContentType(const char* type)
     setResponseHeader("Content-Type", type);
 }
 
-void HTTPResponse::setCookie(const char* name, const char* value, samesite_t sameSiteValue, bool sameSiteFallback)
+void HTTPResponse::setCookie(const char* name, const char* value, time_t expires, samesite_t sameSiteValue)
 {
+    setCookie(name, value, expires, sameSiteValue, false);
+}
+
+void HTTPResponse::setCookie(const char* name, const char* value, time_t expires, samesite_t sameSiteValue, bool sameSiteFallback)
+{
+    string decoratedValue;
+    if (!value) {
+        decoratedValue += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
+    }
+    else {
+        decoratedValue = value;
+        if (expires > 0) {
+            expires += time(nullptr);
+#ifndef HAVE_GMTIME_R
+            struct tm* ptime = gmtime(&expires);
+#else
+            struct tm res;
+            struct tm* ptime = gmtime_r(&expires, &res);
+#endif
+            char cookietimebuf[64];
+            strftime(cookietimebuf, 64, "; expires=%a, %d %b %Y %H:%M:%S GMT", ptime);
+            decoratedValue.append(cookietimebuf);
+        }
+    }
+
     if (sameSiteValue != SAMESITE_ABSENT) {
         // Add SameSite to the primary cookie and optionally set a fallback cookie without SameSite.
-        string ssCookie(name);
-        ssCookie.append("=").append(value).append("; SameSite=");
         switch (sameSiteValue) {
             case SAMESITE_NONE:
-                ssCookie.append("None");
                 if (sameSiteFallback) {
                     string hackedName(name);
-                    setResponseHeader("Set-Cookie", hackedName.append("_fgwars=").append(value).c_str());
+                    setResponseHeader("Set-Cookie", hackedName.append("_fgwars=").append(decoratedValue).c_str());
                 }
+                decoratedValue.append("; SameSite=None");
                 break;
             case SAMESITE_LAX:
-                ssCookie.append("Lax");
+                decoratedValue.append("; SameSite=Lax");
                 break;
             case SAMESITE_STRICT:
-                ssCookie.append("Strict");
+                decoratedValue.append("; SameSite=Strict");
                 break;
             default:
                 throw IOException("Invalid SameSite value supplied");
         }
-        setResponseHeader("Set-Cookie", ssCookie.c_str());
+        string header(name);
+        setResponseHeader("Set-Cookie", header.append("=").append(decoratedValue).c_str());
     }
     else {
-        string cookie(name);
-        setResponseHeader("Set-Cookie", cookie.append("=").append(value).c_str());
+        string header(name);
+        setResponseHeader("Set-Cookie", header.append("=").append(decoratedValue).c_str());
     }
 }
 
diff --git a/xmltooling/io/HTTPResponse.h b/xmltooling/io/HTTPResponse.h
index 513f98f..67c6de1 100644
--- a/xmltooling/io/HTTPResponse.h
+++ b/xmltooling/io/HTTPResponse.h
@@ -74,20 +74,41 @@ namespace xmltooling {
         };
 
         /**
-         * Sets a client cookie.
-         * 
-         * The boolean flag enables the workaround for older clients with
-         * broken SameSite support by setting a second cookie with
-         * a decorated name that would not carry the SameSite flag.
+        * Sets or unsets a client cookie.
+        * 
+        * <p>The boolean flag enables the workaround for older clients with
+        * broken SameSite support by setting a second cookie with
+        * a decorated name that would not carry the SameSite flag.</p>
+        *
+        * @param name  cookie name
+        * @param value value to set, or nullptr to clear
+        * @param expires optional expiration time for the cookie, 0 means session
+        * @param sameSiteValue the SameSite value to apply to the cookie
+        * @param sameSiteFallback enables setting of a fallback cookie
+        */
+        virtual void setCookie(
+            const char* name,
+            const char* value,
+            time_t expires,
+            samesite_t sameSiteValue,
+            bool sameSiteFallback);
+
+        /**
+         * Sets or unsets a client cookie.
+         *
+         * <p>Now defaults to calling the new version with a false flag.</p>
          *
          * @param name  cookie name
          * @param value value to set, or nullptr to clear
+         * @param expires optional expiration time for the cookie, 0 means session
          * @param sameSiteValue the SameSite value to apply to the cookie
-         * @param sameSiteFallback enables setting of a fallback cookie
          */
-        virtual void setCookie(const char* name, const char* value,
-            samesite_t sameSiteValue = SAMESITE_ABSENT, bool sameSiteFallback = false);
-        
+        virtual void setCookie(
+            const char* name,
+            const char* value,
+            time_t expires = 0,
+            samesite_t sameSiteValue = SAMESITE_ABSENT);
+
         /**
          * Redirect the client to the specified URL and complete the response.
          * 

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list