[cpp-sp] branch master updated: CPPOST-112 - Clean up message correlation in relevant policy rules
Scott Cantor
cantor.2 at osu.edu
Tue Feb 11 13:00:57 EST 2020
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch master
in repository cpp-sp.
View the commit online:
http://git.shibboleth.net/view/?p=cpp-sp.git;a=commit;h=b45b3419236223fb368ddee1d83df42ef201e4ce
The following commit(s) were added to refs/heads/master by this push:
new b45b341 CPPOST-112 - Clean up message correlation in relevant policy rules
b45b341 is described below
commit b45b3419236223fb368ddee1d83df42ef201e4ce
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Feb 11 12:59:31 2020 -0500
CPPOST-112 - Clean up message correlation in relevant policy rules
https://issues.shibboleth.net/jira/browse/CPPOST-112
Refactor cookie handling.
Adjust various bits to enable correlation checking.
Turn off bearer rule correlation checks by default.
---
adfs/adfs.cpp | 17 +++-
plugins/AttributeResolverHandler.cpp | 4 +-
schemas/shibboleth-2.0-native-sp-config.xsd | 96 +++++++++---------
schemas/shibboleth-3.0-native-sp-config.xsd | 98 ++++++++++---------
shibsp/AbstractSPRequest.cpp | 48 +++++++++
shibsp/AbstractSPRequest.h | 2 +
shibsp/Application.cpp | 23 +++++
shibsp/Application.h | 13 +++
shibsp/handler/AbstractHandler.h | 2 +-
shibsp/handler/RemotedHandler.h | 26 ++++-
shibsp/handler/impl/AbstractHandler.cpp | 118 ++++++++++-------------
shibsp/handler/impl/AdminLogoutInitiator.cpp | 4 +-
shibsp/handler/impl/AssertionConsumerService.cpp | 6 +-
shibsp/handler/impl/AssertionLookup.cpp | 4 +-
shibsp/handler/impl/ExternalAuthHandler.cpp | 6 +-
shibsp/handler/impl/LocalLogoutInitiator.cpp | 4 +-
shibsp/handler/impl/MetadataGenerator.cpp | 2 +-
shibsp/handler/impl/RemotedHandler.cpp | 77 ++++++++++++++-
shibsp/handler/impl/SAML2ArtifactResolution.cpp | 6 +-
shibsp/handler/impl/SAML2Logout.cpp | 6 +-
shibsp/handler/impl/SAML2LogoutInitiator.cpp | 4 +-
shibsp/handler/impl/SAML2NameIDMgmt.cpp | 6 +-
shibsp/handler/impl/SAML2SessionInitiator.cpp | 2 +-
shibsp/handler/impl/Shib1SessionInitiator.cpp | 2 +-
shibsp/handler/impl/StatusHandler.cpp | 4 +-
shibsp/impl/StorageServiceSessionCache.cpp | 100 +++++--------------
shibsp/impl/StorageServiceSessionCache.h | 4 +-
shibsp/impl/XMLApplication.cpp | 9 ++
28 files changed, 414 insertions(+), 279 deletions(-)
diff --git a/adfs/adfs.cpp b/adfs/adfs.cpp
index 1933867..6eb4ff7 100644
--- a/adfs/adfs.cpp
+++ b/adfs/adfs.cpp
@@ -99,7 +99,12 @@ namespace {
return m_ns.get();
}
- XMLObject* decode(string& relayState, const GenericRequest& genericRequest, SecurityPolicy& policy) const;
+ XMLObject* decode(
+ string& relayState,
+ const GenericRequest& genericRequest,
+ const GenericResponse* genericResponse,
+ SecurityPolicy& policy
+ ) const;
protected:
void extractMessageDetails(
@@ -473,7 +478,7 @@ void ADFSSessionInitiator::receive(DDF& in, ostream& out)
DDFJanitor jout(ret);
// Wrap the outgoing object with a Response facade.
- scoped_ptr<HTTPResponse> http(getResponse(ret));
+ scoped_ptr<HTTPResponse> http(getResponse(*app, ret));
string relayState(in["RelayState"].string() ? in["RelayState"].string() : "");
@@ -574,7 +579,9 @@ pair<bool,long> ADFSSessionInitiator::doRequest(
#ifndef SHIBSP_LITE
-XMLObject* ADFSDecoder::decode(string& relayState, const GenericRequest& genericRequest, SecurityPolicy& policy) const
+XMLObject* ADFSDecoder::decode(
+ string& relayState, const GenericRequest& genericRequest, const GenericResponse*, SecurityPolicy& policy
+ ) const
{
#ifdef _DEBUG
xmltooling::NDC ndc("decode");
@@ -894,12 +901,12 @@ void ADFSLogoutInitiator::receive(DDF& in, ostream& out)
}
// Unpack the request.
- scoped_ptr<HTTPRequest> req(getRequest(in));
+ scoped_ptr<HTTPRequest> req(getRequest(*app, in));
// Set up a response shim.
DDF ret(nullptr);
DDFJanitor jout(ret);
- scoped_ptr<HTTPResponse> resp(getResponse(ret));
+ scoped_ptr<HTTPResponse> resp(getResponse(*app, ret));
Session* session = nullptr;
try {
diff --git a/plugins/AttributeResolverHandler.cpp b/plugins/AttributeResolverHandler.cpp
index d12a38f..5b5b65a 100644
--- a/plugins/AttributeResolverHandler.cpp
+++ b/plugins/AttributeResolverHandler.cpp
@@ -235,8 +235,8 @@ void AttributeResolverHandler::receive(DDF& in, ostream& out)
// Wrap a response shim.
DDF ret(nullptr);
DDFJanitor jout(ret);
- scoped_ptr<HTTPResponse> resp(getResponse(ret));
- scoped_ptr<HTTPRequest> req(getRequest(in));
+ scoped_ptr<HTTPResponse> resp(getResponse(*app, ret));
+ scoped_ptr<HTTPRequest> req(getRequest(*app, in));
// Since we're remoted, the result should either be a throw, a false/0 return,
// which we just return as an empty structure, or a response/redirect,
diff --git a/schemas/shibboleth-2.0-native-sp-config.xsd b/schemas/shibboleth-2.0-native-sp-config.xsd
index 82c8565..50ae8db 100644
--- a/schemas/shibboleth-2.0-native-sp-config.xsd
+++ b/schemas/shibboleth-2.0-native-sp-config.xsd
@@ -33,8 +33,14 @@
<list itemType="conf:string"/>
</simpleType>
+ <simpleType name="anyURI">
+ <restriction base="anyURI">
+ <minLength value="1"/>
+ </restriction>
+ </simpleType>
+
<simpleType name="listOfURIs">
- <list itemType="anyURI"/>
+ <list itemType="conf:anyURI"/>
</simpleType>
<simpleType name="bindingBoolean">
@@ -76,7 +82,7 @@
<sequence>
<any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
- <attribute name="path" type="anyURI" use="required"/>
+ <attribute name="path" type="conf:anyURI" use="required"/>
<attribute name="fatal" type="boolean"/>
<anyAttribute namespace="##any" processContents="lax"/>
</complexType>
@@ -146,7 +152,7 @@
<element name="Extensions" type="conf:ExtensionsType" minOccurs="0"/>
<any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
- <attribute name="logger" type="anyURI"/>
+ <attribute name="logger" type="conf:anyURI"/>
<attribute name="tranLogFormat" type="conf:string"/>
<attribute name="tranLogFiller" type="conf:string"/>
<attribute name="catchAll" type="boolean"/>
@@ -186,7 +192,7 @@
</element>
<any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
- <attribute name="logger" type="anyURI"/>
+ <attribute name="logger" type="conf:anyURI"/>
<attribute name="unsetHeaderValue" type="conf:string"/>
<attribute name="checkSpoofing" type="boolean"/>
<attribute name="spoofKey" type="conf:string"/>
@@ -243,28 +249,28 @@
<attribute name="authType" type="conf:string"/>
<attribute name="requireSession" type="boolean"/>
<attribute name="requireSessionWith" type="conf:string"/>
- <attribute name="requireLogoutWith" type="anyURI"/>
+ <attribute name="requireLogoutWith" type="conf:anyURI"/>
<attribute name="exportAssertion" type="boolean"/>
<attribute name="exportStdVars" type="boolean"/>
<attribute name="exportCookie" type="boolean"/>
<attribute name="exportDuplicateValues" type="boolean"/>
<attribute name="redirectToSSL" type="unsignedInt"/>
- <attribute name="entityID" type="anyURI"/>
- <attribute name="discoveryURL" type="anyURI"/>
+ <attribute name="entityID" type="conf:anyURI"/>
+ <attribute name="discoveryURL" type="conf:anyURI"/>
<attribute name="discoveryPolicy" type="conf:string"/>
<attribute name="isPassive" type="boolean"/>
<attribute name="returnOnError" type="boolean"/>
<attribute name="forceAuthn" type="boolean"/>
<attribute name="authnContextClassRef" type="conf:listOfURIs"/>
<attribute name="authnContextComparison" type="samlp:AuthnContextComparisonType"/>
- <attribute name="NameIDFormat" type="anyURI"/>
+ <attribute name="NameIDFormat" type="conf:anyURI"/>
<attribute name="SPNameQualifier" type="conf:string"/>
- <attribute name="redirectErrors" type="anyURI"/>
- <attribute name="sessionError" type="anyURI"/>
- <attribute name="metadataError" type="anyURI"/>
- <attribute name="accessError" type="anyURI"/>
- <attribute name="sslError" type="anyURI"/>
- <attribute name="target" type="anyURI"/>
+ <attribute name="redirectErrors" type="conf:anyURI"/>
+ <attribute name="sessionError" type="conf:anyURI"/>
+ <attribute name="metadataError" type="conf:anyURI"/>
+ <attribute name="accessError" type="conf:anyURI"/>
+ <attribute name="sslError" type="conf:anyURI"/>
+ <attribute name="target" type="conf:anyURI"/>
<attribute name="acsIndex" type="unsignedShort"/>
<attribute name="REMOTE_ADDR" type="conf:string"/>
<attribute name="encoding" type="conf:string"/>
@@ -410,7 +416,7 @@
</choice>
</sequence>
<attribute name="id" type="conf:string" fixed="default"/>
- <attribute name="entityID" type="anyURI" use="required"/>
+ <attribute name="entityID" type="conf:anyURI" use="required"/>
<attributeGroup ref="conf:ApplicationGroup"/>
<attributeGroup ref="conf:RelyingPartyGroup"/>
<anyAttribute namespace="##other" processContents="lax"/>
@@ -436,14 +442,14 @@
</choice>
</sequence>
<attribute name="id" type="conf:string" use="required"/>
- <attribute name="entityID" type="anyURI"/>
+ <attribute name="entityID" type="conf:anyURI"/>
<attributeGroup ref="conf:ApplicationGroup"/>
<attributeGroup ref="conf:RelyingPartyGroup"/>
<anyAttribute namespace="##other" processContents="lax"/>
</complexType>
<attributeGroup name="ApplicationGroup">
- <attribute name="homeURL" type="anyURI"/>
+ <attribute name="homeURL" type="conf:anyURI"/>
<attribute name="policyId" type="conf:string"/>
<attribute name="REMOTE_USER" type="conf:listOfStrings"/>
<attribute name="unsetHeaders" type="conf:listOfStrings"/>
@@ -457,10 +463,10 @@
<attribute name="authUsername" type="conf:string"/>
<attribute name="authPassword" type="conf:string"/>
<attribute name="signing" type="conf:bindingBoolean"/>
- <attribute name="signingAlg" type="anyURI"/>
- <attribute name="digestAlg" type="anyURI"/>
+ <attribute name="signingAlg" type="conf:anyURI"/>
+ <attribute name="digestAlg" type="conf:anyURI"/>
<attribute name="encryption" type="conf:bindingBoolean"/>
- <attribute name="encryptionAlg" type="anyURI"/>
+ <attribute name="encryptionAlg" type="conf:anyURI"/>
<attribute name="keyName" type="conf:string"/>
<attribute name="artifactEndpointIndex" type="unsignedShort"/>
<attribute name="chunkedEncoding" type="boolean"/>
@@ -470,11 +476,11 @@
<attribute name="requireConfidentiality" type="boolean"/>
<attribute name="requireTransportAuth" type="boolean"/>
<attribute name="requireSignedAssertions" type="boolean"/>
- <attribute name="sessionHook" type="anyURI"/>
+ <attribute name="sessionHook" type="conf:anyURI"/>
<attribute name="artifactByFilesystem" type="boolean"/>
<attribute name="authnContextClassRef" type="conf:listOfURIs"/>
<attribute name="authnContextComparison" type="samlp:AuthnContextComparisonType"/>
- <attribute name="NameIDFormat" type="anyURI"/>
+ <attribute name="NameIDFormat" type="conf:anyURI"/>
<attribute name="SPNameQualifier" type="conf:string"/>
<attribute name="requestDelegation" type="boolean"/>
</attributeGroup>
@@ -494,7 +500,7 @@
<attribute name="policyId" type="conf:string"/>
<attribute name="ignoreNoPassive" type="boolean"/>
<attribute name="discoveryProtocol" type="conf:string"/>
- <attribute name="discoveryURL" type="anyURI"/>
+ <attribute name="discoveryURL" type="conf:anyURI"/>
<attributeGroup ref="conf:SessionInitiatorGroup"/>
</extension>
</simpleContent>
@@ -535,7 +541,7 @@
<element ref="conf:Handler"/>
</choice>
</sequence>
- <attribute name="handlerURL" type="anyURI"/>
+ <attribute name="handlerURL" type="conf:anyURI"/>
<attribute name="handlerSSL" type="boolean"/>
<attribute name="exportLocation" type="conf:string"/>
<attribute name="exportACL" type="conf:listOfStrings"/>
@@ -592,21 +598,21 @@
</annotation>
<attribute name="relayState" type="conf:string"/>
<attribute name="entityIDParam" type="conf:string"/>
- <attribute name="entityID" type="anyURI"/>
+ <attribute name="entityID" type="conf:anyURI"/>
<attribute name="outgoingBindings" type="conf:listOfURIs"/>
<attribute name="preservedOptions" type="conf:listOfStrings"/>
- <attribute name="template" type="anyURI"/>
+ <attribute name="template" type="conf:anyURI"/>
<attribute name="postArtifact" type="boolean"/>
<attribute name="acsByIndex" type="boolean"/>
<attribute name="isPassive" type="boolean"/>
<attribute name="returnOnError" type="boolean"/>
<attribute name="forceAuthn" type="boolean"/>
- <attribute name="authnContextClassRef" type="anyURI"/>
+ <attribute name="authnContextClassRef" type="conf:anyURI"/>
<attribute name="authnContextComparison" type="samlp:AuthnContextComparisonType"/>
- <attribute name="NameIDFormat" type="anyURI"/>
+ <attribute name="NameIDFormat" type="conf:anyURI"/>
<attribute name="SPNameQualifier" type="conf:string"/>
<attribute name="requestDelegation" type="boolean"/>
- <attribute name="target" type="anyURI"/>
+ <attribute name="target" type="conf:anyURI"/>
<attribute name="discoveryPolicy" type="conf:string"/>
<attribute name="signing" type="conf:bindingBoolean"/>
<attribute name="encryption" type="conf:bindingBoolean"/>
@@ -624,10 +630,10 @@
<sequence>
<any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
- <attribute name="Location" type="anyURI"/>
+ <attribute name="Location" type="conf:anyURI"/>
<attribute name="id" type="conf:string"/>
<attribute name="isDefault" type="boolean"/>
- <attribute name="URL" type="anyURI"/>
+ <attribute name="URL" type="conf:anyURI"/>
<attribute name="acsIndex" type="unsignedShort"/>
<attribute name="defaultACSIndex" type="unsignedShort"/> <!-- deprecated -->
<attributeGroup ref="conf:SessionInitiatorGroup"/>
@@ -642,7 +648,7 @@
</annotation>
<attribute name="relayState" type="conf:string"/>
<attribute name="outgoingBindings" type="conf:listOfURIs"/>
- <attribute name="template" type="anyURI"/>
+ <attribute name="template" type="conf:anyURI"/>
<attribute name="postArtifact" type="boolean"/>
<attribute name="signing" type="conf:bindingBoolean"/>
<attribute name="encryption" type="conf:bindingBoolean"/>
@@ -659,7 +665,7 @@
<sequence>
<any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
- <attribute name="Location" type="anyURI"/>
+ <attribute name="Location" type="conf:anyURI"/>
<attributeGroup ref="conf:LogoutInitiatorGroup"/>
</restriction>
</complexContent>
@@ -676,7 +682,7 @@
<sequence>
<any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
- <attribute name="Location" type="anyURI" use="required"/>
+ <attribute name="Location" type="conf:anyURI" use="required"/>
<attribute name="acl" type="conf:listOfStrings"/>
<anyAttribute namespace="##any" processContents="lax"/>
</restriction>
@@ -691,14 +697,14 @@
<sequence>
<any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
- <attribute name="redirectErrors" type="anyURI"/>
- <attribute name="session" type="anyURI"/>
- <attribute name="metadata" type="anyURI"/>
- <attribute name="access" type="anyURI"/>
- <attribute name="ssl" type="anyURI"/>
- <attribute name="localLogout" type="anyURI"/>
- <attribute name="globalLogout" type="anyURI"/>
- <attribute name="partialLogout" type="anyURI"/>
+ <attribute name="redirectErrors" type="conf:anyURI"/>
+ <attribute name="session" type="conf:anyURI"/>
+ <attribute name="metadata" type="conf:anyURI"/>
+ <attribute name="access" type="conf:anyURI"/>
+ <attribute name="ssl" type="conf:anyURI"/>
+ <attribute name="localLogout" type="conf:anyURI"/>
+ <attribute name="globalLogout" type="conf:anyURI"/>
+ <attribute name="partialLogout" type="conf:anyURI"/>
<anyAttribute namespace="##any" processContents="lax"/>
</complexType>
@@ -712,7 +718,7 @@
<attribute name="Name" type="conf:string"/>
<attribute name="type" type="conf:string"/>
<attributeGroup ref="conf:RelyingPartyGroup"/>
- <attribute name="entityID" type="anyURI"/>
+ <attribute name="entityID" type="conf:anyURI"/>
<anyAttribute namespace="##any" processContents="lax"/>
</complexType>
@@ -729,7 +735,7 @@
</restriction>
</simpleType>
</attribute>
- <attribute name="Location" type="anyURI" use="required"/>
+ <attribute name="Location" type="conf:anyURI" use="required"/>
<anyAttribute namespace="##any" processContents="lax"/>
</complexType>
@@ -826,7 +832,7 @@
<element ref="conf:TransportOption" minOccurs="0" maxOccurs="unbounded"/>
<element ref="ds:Signature" minOccurs="0"/>
</sequence>
- <attribute name="logger" type="anyURI"/>
+ <attribute name="logger" type="conf:anyURI"/>
<attribute name="clockSkew" type="unsignedInt"/>
<attribute name="unsafeChars" type="conf:string"/>
<attribute name="allowedSchemes" type="conf:listOfStrings"/>
diff --git a/schemas/shibboleth-3.0-native-sp-config.xsd b/schemas/shibboleth-3.0-native-sp-config.xsd
index 2a8a274..564c389 100644
--- a/schemas/shibboleth-3.0-native-sp-config.xsd
+++ b/schemas/shibboleth-3.0-native-sp-config.xsd
@@ -33,8 +33,14 @@
<list itemType="conf:string"/>
</simpleType>
+ <simpleType name="anyURI">
+ <restriction base="anyURI">
+ <minLength value="1"/>
+ </restriction>
+ </simpleType>
+
<simpleType name="listOfURIs">
- <list itemType="anyURI"/>
+ <list itemType="conf:anyURI"/>
</simpleType>
<simpleType name="bindingBoolean">
@@ -84,7 +90,7 @@
<sequence>
<any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
- <attribute name="path" type="anyURI" use="required"/>
+ <attribute name="path" type="conf:anyURI" use="required"/>
<attribute name="fatal" type="boolean"/>
<anyAttribute namespace="##any" processContents="lax"/>
</complexType>
@@ -170,7 +176,7 @@
<element name="Extensions" type="conf:ExtensionsType" minOccurs="0"/>
<any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
- <attribute name="logger" type="anyURI"/>
+ <attribute name="logger" type="conf:anyURI"/>
<attribute name="tranLogFormat" type="conf:string"/>
<attribute name="tranLogFiller" type="conf:string"/>
<attribute name="catchAll" type="boolean"/>
@@ -221,7 +227,7 @@
</element>
<any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
- <attribute name="logger" type="anyURI"/>
+ <attribute name="logger" type="conf:anyURI"/>
<attribute name="unsetHeaderValue" type="conf:string"/>
<attribute name="checkSpoofing" type="boolean"/>
<attribute name="spoofKey" type="conf:string"/>
@@ -277,29 +283,29 @@
<attribute name="authType" type="conf:string"/>
<attribute name="requireSession" type="boolean"/>
<attribute name="requireSessionWith" type="conf:string"/>
- <attribute name="requireLogoutWith" type="anyURI"/>
+ <attribute name="requireLogoutWith" type="conf:anyURI"/>
<attribute name="exportAssertion" type="boolean"/>
<attribute name="exportStdVars" type="boolean"/>
<attribute name="exportCookie" type="boolean"/>
<attribute name="exportDuplicateValues" type="boolean"/>
<attribute name="redirectToSSL" type="unsignedInt"/>
- <attribute name="entityID" type="anyURI"/>
- <attribute name="entityIDSelf" type="anyURI"/>
- <attribute name="discoveryURL" type="anyURI"/>
+ <attribute name="entityID" type="conf:anyURI"/>
+ <attribute name="entityIDSelf" type="conf:anyURI"/>
+ <attribute name="discoveryURL" type="conf:anyURI"/>
<attribute name="discoveryPolicy" type="conf:string"/>
<attribute name="isPassive" type="boolean"/>
<attribute name="returnOnError" type="boolean"/>
<attribute name="forceAuthn" type="boolean"/>
<attribute name="authnContextClassRef" type="conf:listOfURIs"/>
<attribute name="authnContextComparison" type="samlp:AuthnContextComparisonType"/>
- <attribute name="NameIDFormat" type="anyURI"/>
+ <attribute name="NameIDFormat" type="conf:anyURI"/>
<attribute name="SPNameQualifier" type="conf:string"/>
- <attribute name="redirectErrors" type="anyURI"/>
- <attribute name="sessionError" type="anyURI"/>
- <attribute name="metadataError" type="anyURI"/>
- <attribute name="accessError" type="anyURI"/>
- <attribute name="sslError" type="anyURI"/>
- <attribute name="target" type="anyURI"/>
+ <attribute name="redirectErrors" type="conf:anyURI"/>
+ <attribute name="sessionError" type="conf:anyURI"/>
+ <attribute name="metadataError" type="conf:anyURI"/>
+ <attribute name="accessError" type="conf:anyURI"/>
+ <attribute name="sslError" type="conf:anyURI"/>
+ <attribute name="target" type="conf:anyURI"/>
<attribute name="acsIndex" type="unsignedShort"/>
<attribute name="REMOTE_ADDR" type="conf:string"/>
<attribute name="encoding" type="conf:string"/>
@@ -445,7 +451,7 @@
</choice>
</sequence>
<attribute name="id" type="conf:string" fixed="default"/>
- <attribute name="entityID" type="anyURI" use="required"/>
+ <attribute name="entityID" type="conf:anyURI" use="required"/>
<attributeGroup ref="conf:ApplicationGroup"/>
<attributeGroup ref="conf:RelyingPartyGroup"/>
<anyAttribute namespace="##other" processContents="lax"/>
@@ -472,7 +478,7 @@
</choice>
</sequence>
<attribute name="id" type="conf:string" use="required"/>
- <attribute name="entityID" type="anyURI"/>
+ <attribute name="entityID" type="conf:anyURI"/>
<attributeGroup ref="conf:ApplicationGroup"/>
<attributeGroup ref="conf:RelyingPartyGroup"/>
<anyAttribute namespace="##other" processContents="lax"/>
@@ -487,7 +493,7 @@
</complexType>
<attributeGroup name="ApplicationGroup">
- <attribute name="homeURL" type="anyURI"/>
+ <attribute name="homeURL" type="conf:anyURI"/>
<attribute name="policyId" type="conf:string"/>
<attribute name="REMOTE_USER" type="conf:listOfStrings"/>
<attribute name="unsetHeaders" type="conf:listOfStrings"/>
@@ -501,10 +507,10 @@
<attribute name="authUsername" type="conf:string"/>
<attribute name="authPassword" type="conf:string"/>
<attribute name="signing" type="conf:bindingBoolean"/>
- <attribute name="signingAlg" type="anyURI"/>
- <attribute name="digestAlg" type="anyURI"/>
+ <attribute name="signingAlg" type="conf:anyURI"/>
+ <attribute name="digestAlg" type="conf:anyURI"/>
<attribute name="encryption" type="conf:bindingBoolean"/>
- <attribute name="encryptionAlg" type="anyURI"/>
+ <attribute name="encryptionAlg" type="conf:anyURI"/>
<attribute name="keyName" type="conf:string"/>
<attribute name="artifactEndpointIndex" type="unsignedShort"/>
<attribute name="chunkedEncoding" type="boolean"/>
@@ -514,11 +520,11 @@
<attribute name="requireConfidentiality" type="boolean"/>
<attribute name="requireTransportAuth" type="boolean"/>
<attribute name="requireSignedAssertions" type="boolean"/>
- <attribute name="sessionHook" type="anyURI"/>
+ <attribute name="sessionHook" type="conf:anyURI"/>
<attribute name="artifactByFilesystem" type="boolean"/>
<attribute name="authnContextClassRef" type="conf:listOfURIs"/>
<attribute name="authnContextComparison" type="samlp:AuthnContextComparisonType"/>
- <attribute name="NameIDFormat" type="anyURI"/>
+ <attribute name="NameIDFormat" type="conf:anyURI"/>
<attribute name="SPNameQualifier" type="conf:string"/>
<attribute name="requestDelegation" type="boolean"/>
</attributeGroup>
@@ -538,7 +544,7 @@
<attribute name="policyId" type="conf:string"/>
<attribute name="ignoreNoPassive" type="boolean"/>
<attribute name="discoveryProtocol" type="conf:string"/>
- <attribute name="discoveryURL" type="anyURI"/>
+ <attribute name="discoveryURL" type="conf:anyURI"/>
<attributeGroup ref="conf:SessionInitiatorGroup"/>
</extension>
</simpleContent>
@@ -579,7 +585,7 @@
<element ref="conf:Handler"/>
</choice>
</sequence>
- <attribute name="handlerURL" type="anyURI"/>
+ <attribute name="handlerURL" type="conf:anyURI"/>
<attribute name="handlerSSL" type="boolean"/>
<attribute name="exportLocation" type="conf:string"/>
<attribute name="exportACL" type="conf:listOfStrings"/>
@@ -638,21 +644,21 @@
</annotation>
<attribute name="relayState" type="conf:string"/>
<attribute name="entityIDParam" type="conf:string"/>
- <attribute name="entityID" type="anyURI"/>
+ <attribute name="entityID" type="conf:anyURI"/>
<attribute name="outgoingBindings" type="conf:listOfURIs"/>
<attribute name="preservedOptions" type="conf:listOfStrings"/>
- <attribute name="template" type="anyURI"/>
+ <attribute name="template" type="conf:anyURI"/>
<attribute name="postArtifact" type="boolean"/>
<attribute name="acsByIndex" type="boolean"/>
<attribute name="isPassive" type="boolean"/>
<attribute name="returnOnError" type="boolean"/>
<attribute name="forceAuthn" type="boolean"/>
- <attribute name="authnContextClassRef" type="anyURI"/>
+ <attribute name="authnContextClassRef" type="conf:anyURI"/>
<attribute name="authnContextComparison" type="samlp:AuthnContextComparisonType"/>
- <attribute name="NameIDFormat" type="anyURI"/>
+ <attribute name="NameIDFormat" type="conf:anyURI"/>
<attribute name="SPNameQualifier" type="conf:string"/>
<attribute name="requestDelegation" type="boolean"/>
- <attribute name="target" type="anyURI"/>
+ <attribute name="target" type="conf:anyURI"/>
<attribute name="discoveryPolicy" type="conf:string"/>
<attribute name="signing" type="conf:bindingBoolean"/>
<attribute name="encryption" type="conf:bindingBoolean"/>
@@ -670,10 +676,10 @@
<sequence>
<any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
- <attribute name="Location" type="anyURI"/>
+ <attribute name="Location" type="conf:anyURI"/>
<attribute name="id" type="conf:string"/>
<attribute name="isDefault" type="boolean"/>
- <attribute name="URL" type="anyURI"/>
+ <attribute name="URL" type="conf:anyURI"/>
<attribute name="acsIndex" type="unsignedShort"/>
<attributeGroup ref="conf:SessionInitiatorGroup"/>
</restriction>
@@ -687,7 +693,7 @@
</annotation>
<attribute name="relayState" type="conf:string"/>
<attribute name="outgoingBindings" type="conf:listOfURIs"/>
- <attribute name="template" type="anyURI"/>
+ <attribute name="template" type="conf:anyURI"/>
<attribute name="postArtifact" type="boolean"/>
<attribute name="signing" type="conf:bindingBoolean"/>
<attribute name="encryption" type="conf:bindingBoolean"/>
@@ -704,7 +710,7 @@
<sequence>
<any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
- <attribute name="Location" type="anyURI"/>
+ <attribute name="Location" type="conf:anyURI"/>
<attributeGroup ref="conf:LogoutInitiatorGroup"/>
</restriction>
</complexContent>
@@ -721,7 +727,7 @@
<sequence>
<any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
- <attribute name="Location" type="anyURI" use="required"/>
+ <attribute name="Location" type="conf:anyURI" use="required"/>
<attribute name="acl" type="conf:listOfStrings"/>
<anyAttribute namespace="##any" processContents="lax"/>
</restriction>
@@ -736,14 +742,14 @@
<sequence>
<any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
- <attribute name="redirectErrors" type="anyURI"/>
- <attribute name="session" type="anyURI"/>
- <attribute name="metadata" type="anyURI"/>
- <attribute name="access" type="anyURI"/>
- <attribute name="ssl" type="anyURI"/>
- <attribute name="localLogout" type="anyURI"/>
- <attribute name="globalLogout" type="anyURI"/>
- <attribute name="partialLogout" type="anyURI"/>
+ <attribute name="redirectErrors" type="conf:anyURI"/>
+ <attribute name="session" type="conf:anyURI"/>
+ <attribute name="metadata" type="conf:anyURI"/>
+ <attribute name="access" type="conf:anyURI"/>
+ <attribute name="ssl" type="conf:anyURI"/>
+ <attribute name="localLogout" type="conf:anyURI"/>
+ <attribute name="globalLogout" type="conf:anyURI"/>
+ <attribute name="partialLogout" type="conf:anyURI"/>
<anyAttribute namespace="##any" processContents="lax"/>
</complexType>
@@ -757,7 +763,7 @@
<attribute name="Name" type="conf:string"/>
<attribute name="type" type="conf:string"/>
<attributeGroup ref="conf:RelyingPartyGroup"/>
- <attribute name="entityID" type="anyURI"/>
+ <attribute name="entityID" type="conf:anyURI"/>
<anyAttribute namespace="##any" processContents="lax"/>
</complexType>
@@ -774,7 +780,7 @@
</restriction>
</simpleType>
</attribute>
- <attribute name="Location" type="anyURI" use="required"/>
+ <attribute name="Location" type="conf:anyURI" use="required"/>
<anyAttribute namespace="##any" processContents="lax"/>
</complexType>
@@ -869,7 +875,7 @@
<element ref="conf:TransportOption" minOccurs="0" maxOccurs="unbounded"/>
<element ref="ds:Signature" minOccurs="0"/>
</sequence>
- <attribute name="logger" type="anyURI"/>
+ <attribute name="logger" type="conf:anyURI"/>
<attribute name="clockSkew" type="unsignedInt"/>
<attribute name="unsafeChars" type="conf:string"/>
<attribute name="allowedSchemes" type="conf:listOfStrings"/>
diff --git a/shibsp/AbstractSPRequest.cpp b/shibsp/AbstractSPRequest.cpp
index 68f6b23..5bc3d67 100644
--- a/shibsp/AbstractSPRequest.cpp
+++ b/shibsp/AbstractSPRequest.cpp
@@ -343,6 +343,54 @@ void AbstractSPRequest::setAuthType(const char* authtype)
}
+const char* AbstractSPRequest::getCookie(const char* name) const
+{
+ pair<bool, bool> sameSiteFallback = pair<bool, bool>(false, false);
+ const PropertySet* props = getApplication().getPropertySet("Sessions");
+ if (props) {
+ sameSiteFallback = props->getBool("sameSiteFallback");
+ }
+ return HTTPRequest::getCookie(name, sameSiteFallback.first && sameSiteFallback.second);
+}
+
+void AbstractSPRequest::setCookie(const char* name, const char* value, time_t expires, samesite_t sameSite)
+{
+ static const char* defProps="; path=/; HttpOnly";
+ static const char* sslProps="; path=/; secure; HttpOnly";
+
+ const char* cookieProps = defProps;
+ pair<bool,bool> sameSiteFallback = pair<bool,bool>(false, false);
+
+ const PropertySet* props = getApplication().getPropertySet("Sessions");
+ if (props) {
+ if (sameSite == SAMESITE_NONE) {
+ sameSiteFallback = props->getBool("sameSiteFallback");
+ }
+
+ pair<bool, const char*> p = props->getString("cookieProps");
+ if (p.first) {
+ if (!strcmp(p.second, "https"))
+ cookieProps = sslProps;
+ else if (strcmp(p.second, "http"))
+ cookieProps = p.second;
+ }
+ }
+
+ if (cookieProps) {
+ string decoratedValue(value ? value : "");
+ if (!value) {
+ decoratedValue += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
+ }
+ decoratedValue += cookieProps;
+ HTTPResponse::setCookie(name, decoratedValue.c_str(), expires, sameSite,
+ sameSiteFallback.first && sameSiteFallback.second);
+ }
+ else {
+ HTTPResponse::setCookie(name, value, expires, sameSite,
+ sameSiteFallback.first && sameSiteFallback.second);
+ }
+}
+
void AbstractSPRequest::log(SPLogLevel level, const std::string& msg) const
{
reinterpret_cast<Category*>(m_log)->log(
diff --git a/shibsp/AbstractSPRequest.h b/shibsp/AbstractSPRequest.h
index cc6144c..48a2e28 100644
--- a/shibsp/AbstractSPRequest.h
+++ b/shibsp/AbstractSPRequest.h
@@ -75,7 +75,9 @@ namespace shibsp {
std::vector<const char*>::size_type getParameters(const char* name, std::vector<const char*>& values) const;
const char* getHandlerURL(const char* resource=nullptr) const;
std::string getSecureHeader(const char* name) const;
+ const char* getCookie(const char* name) const;
void setAuthType(const char* authtype);
+ void setCookie(const char* name, const char* value, time_t expires = 0, samesite_t sameSite = SAMESITE_ABSENT);
void log(SPLogLevel level, const std::string& msg) const;
bool isPriorityEnabled(SPLogLevel level) const;
diff --git a/shibsp/Application.cpp b/shibsp/Application.cpp
index bc33bca..5ab8507 100644
--- a/shibsp/Application.cpp
+++ b/shibsp/Application.cpp
@@ -60,8 +60,31 @@ const char* Application::getId() const
return ret.first ? ret.second : "default";
}
+string Application::getCookieName(const char* prefix, time_t* lifetime) const
+{
+ if (lifetime)
+ *lifetime = 0;
+ if (!prefix)
+ prefix = "";
+ const PropertySet* props = getPropertySet("Sessions");
+ if (props) {
+ if (lifetime) {
+ pair<bool,unsigned int> lt = props->getUnsignedInt("cookieLifetime");
+ if (lt.first)
+ *lifetime = lt.second;
+ }
+ pair<bool,const char*> p = props->getString("cookieName");
+ if (p.first)
+ return string(prefix) + p.second;
+ }
+
+ return string(prefix) + getHash();
+}
+
pair<string,const char*> Application::getCookieNameProps(const char* prefix, time_t* lifetime) const
{
+ // TODO: remove in V4 if it ever drops.
+
static const char* defProps="; path=/; HttpOnly";
static const char* sslProps="; path=/; secure; HttpOnly";
diff --git a/shibsp/Application.h b/shibsp/Application.h
index 076bfd8..7ba3d73 100644
--- a/shibsp/Application.h
+++ b/shibsp/Application.h
@@ -125,6 +125,19 @@ namespace shibsp {
virtual const char* getHash() const=0;
/**
+ * @Deprecated
+ *
+ * Returns the cookies name to use for this Application.
+ *
+ * @param prefix a value to prepend to the base cookie name
+ * @param lifetime if non-null, will be populated with a suggested lifetime for the cookie, or 0 if session-bound
+ * @return the assigned cookie name to use
+ */
+ virtual std::string getCookieName(const char* prefix, time_t* lifetime=nullptr) const;
+
+ /**
+ * @Deprecated
+ *
* Returns the name and cookie properties to use for this Application.
*
* @param prefix a value to prepend to the base cookie name
diff --git a/shibsp/handler/AbstractHandler.h b/shibsp/handler/AbstractHandler.h
index 567f022..cef160f 100644
--- a/shibsp/handler/AbstractHandler.h
+++ b/shibsp/handler/AbstractHandler.h
@@ -248,7 +248,7 @@ namespace shibsp {
virtual ~AbstractHandler();
private:
- std::pair<std::string,const char*> getPostCookieNameProps(const Application& app, const char* relayState) const;
+ std::string getPostCookieName(const Application& app, const char* relayState) const;
DDF getPostData(const Application& application, const xmltooling::HTTPRequest& request) const;
};
diff --git a/shibsp/handler/RemotedHandler.h b/shibsp/handler/RemotedHandler.h
index f8085d7..a22a5ec 100644
--- a/shibsp/handler/RemotedHandler.h
+++ b/shibsp/handler/RemotedHandler.h
@@ -98,17 +98,41 @@ namespace shibsp {
/**
* Builds a new request instance around a remoted data object.
*
+ * @param app the application
* @param in the dataflow object containing the remoted request
* @return a call-specific request object based on the input, to be freed by the caller
*/
- xmltooling::HTTPRequest* getRequest(DDF& in) const;
+ xmltooling::HTTPRequest* getRequest(const Application& app, DDF& in) const;
/**
* Builds a new response instance around an outgoing data object.
*
+ * @param app the application
* @param out the dataflow object to be returned by the caller
* @return a call-specific response object, to be freed by the caller
*/
+ xmltooling::HTTPResponse* getResponse(const Application& app, DDF& out) const;
+
+ /**
+ * @Deprecated
+ *
+ * Builds a new request instance around a remoted data object.
+ *
+ * @param app the application
+ * @param in the dataflow object containing the remoted request
+ * @return a call-specific request object based on the input, to be freed by the caller
+ */
+ xmltooling::HTTPRequest* getRequest(DDF& in) const;
+
+ /**
+ * @Deprecated
+ *
+ * Builds a new response instance around an outgoing data object.
+ *
+ * @param app the application
+ * @param out the dataflow object to be returned by the caller
+ * @return a call-specific response object, to be freed by the caller
+ */
xmltooling::HTTPResponse* getResponse(DDF& out) const;
/** Message address for remote half. */
diff --git a/shibsp/handler/impl/AbstractHandler.cpp b/shibsp/handler/impl/AbstractHandler.cpp
index 361e38e..e3800e2 100644
--- a/shibsp/handler/impl/AbstractHandler.cpp
+++ b/shibsp/handler/impl/AbstractHandler.cpp
@@ -186,54 +186,60 @@ void Handler::cleanRelayState(
const Application& application, const xmltooling::HTTPRequest& request, xmltooling::HTTPResponse& response
) const
{
- const PropertySet* sessionprop = application.getPropertySet("Sessions");
-
- // Only cookie-based relay state requires cleaning.
pair<bool,const char*> mech = getString("relayState");
if (!mech.first) {
// Check for setting on Sessions element.
+ const PropertySet* sessionprop = application.getPropertySet("Sessions");
if (sessionprop) {
mech = sessionprop->getString("relayState");
}
}
- if (!mech.first || !mech.second || strncmp(mech.second, "cookie", 6))
- return;
- int maxCookies = 20,purgedCookies = 0;
- mech.second += 6;
- if (*mech.second == ':' && isdigit(*(++mech.second))) {
- maxCookies = atoi(mech.second);
- if (maxCookies == 0)
- maxCookies = 20;
- }
+ int maxRSCookies = 20,purgedRSCookies = 0;
+ int maxOSCookies = 20,purgedOSCookies = 0;
- pair<bool, bool> sameSiteFallback =
- sessionprop ? sessionprop->getBool("sameSiteFallback") : pair<bool,bool>(false, false);
-
- string exp;
+ if (mech.first && !strncmp(mech.second, "cookie", 6)) {
+ mech.second += 6;
+ if (*mech.second == ':' && isdigit(*(++mech.second))) {
+ maxRSCookies = maxOSCookies = atoi(mech.second);
+ if (maxRSCookies == 0) {
+ maxRSCookies = maxOSCookies = 20;
+ }
+ }
+ }
// Walk the list of cookies backwards by name.
const map<string,string>& cookies = request.getCookies();
for (map<string,string>::const_reverse_iterator i = cookies.rbegin(); i != cookies.rend(); ++i) {
// Process relay state cookies only.
if (starts_with(i->first, "_shibstate_")) {
- if (maxCookies > 0) {
+ if (maxRSCookies > 0) {
// Keep it, but count it against the limit.
- --maxCookies;
+ --maxRSCookies;
}
else {
// We're over the limit, so everything here and older gets cleaned up.
- if (exp.empty())
- exp = string(application.getCookieNameProps("_shibstate_").second) + "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
- response.setCookie(i->first.c_str(), exp.c_str(), HTTPResponse::SAMESITE_NONE,
- sameSiteFallback.first && sameSiteFallback.second);
- ++purgedCookies;
+ response.setCookie(i->first.c_str(), nullptr, 0, HTTPResponse::SAMESITE_NONE);
+ ++purgedRSCookies;
+ }
+ }
+ else if (starts_with(i->first, "_opensaml_req_")) {
+ if (maxOSCookies > 0) {
+ // Keep it, but count it against the limit.
+ --maxOSCookies;
+ }
+ else {
+ // We're over the limit, so everything here and older gets cleaned up.
+ response.setCookie(i->first.c_str(), nullptr, 0, HTTPResponse::SAMESITE_NONE);
+ ++purgedOSCookies;
}
}
}
- if (purgedCookies > 0)
- log(SPRequest::SPDebug, string("purged ") + lexical_cast<string>(purgedCookies) + " stale relay state cookie(s) from client");
+ if (purgedRSCookies > 0)
+ log(SPRequest::SPDebug, string("purged ") + lexical_cast<string>(purgedRSCookies) + " stale relay state cookie(s) from client");
+ if (purgedOSCookies > 0)
+ log(SPRequest::SPDebug, string("purged ") + lexical_cast<string>(purgedOSCookies) + " stale request correlation cookie(s) from client");
}
void Handler::preserveRelayState(const Application& application, HTTPResponse& response, string& relayState) const
@@ -242,12 +248,11 @@ void Handler::preserveRelayState(const Application& application, HTTPResponse& r
if (relayState.empty())
return;
- const PropertySet* sessionprop = application.getPropertySet("Sessions");
-
// No setting means just pass state by value.
pair<bool,const char*> mech = getString("relayState");
if (!mech.first) {
// Check for setting on Sessions element.
+ const PropertySet* sessionprop = application.getPropertySet("Sessions");
if (sessionprop)
mech = sessionprop->getString("relayState");
}
@@ -258,17 +263,14 @@ void Handler::preserveRelayState(const Application& application, HTTPResponse& r
// Here we store the state in a cookie and send a fixed
// value so we can recognize it on the way back.
if (relayState.find("cookie:") != 0 && relayState.find("ss:") != 0) {
- pair<bool, bool> sameSiteFallback =
- sessionprop ? sessionprop->getBool("sameSiteFallback") : pair<bool,bool>(false, false);
- pair<string,const char*> shib_cookie = application.getCookieNameProps("_shibstate_");
- string stateval = XMLToolingConfig::getConfig().getURLEncoder()->encode(relayState.c_str()) + shib_cookie.second;
// Generate a random key for the cookie name instead of the fixed name.
string rsKey;
generateRandomHex(rsKey, 4);
rsKey = lexical_cast<string>(time(nullptr)) + '_' + rsKey;
- shib_cookie.first = "_shibstate_" + rsKey;
- response.setCookie(shib_cookie.first.c_str(), stateval.c_str(), HTTPResponse::SAMESITE_NONE,
- sameSiteFallback.first && sameSiteFallback.second);
+ string shib_cookie_name = "_shibstate_" + rsKey;
+ response.setCookie(shib_cookie_name.c_str(),
+ XMLToolingConfig::getConfig().getURLEncoder()->encode(relayState.c_str()).c_str(),
+ 0, HTTPResponse::SAMESITE_NONE);
relayState = "cookie:" + rsKey;
}
}
@@ -392,14 +394,9 @@ void Handler::recoverRelayState(
if (strstr(state,"cookie:") == state) {
state += 7;
if (*state) {
- const PropertySet* sessionprop = application.getPropertySet("Sessions");
- pair<bool, bool> sameSiteFallback =
- sessionprop ? sessionprop->getBool("sameSiteFallback") : pair<bool,bool>(false, false);
-
// Pull the value from the "relay state" cookie.
- pair<string,const char*> relay_cookie = application.getCookieNameProps("_shibstate_");
- relay_cookie.first = string("_shibstate_") + state;
- state = request.getCookie(relay_cookie.first.c_str(), sameSiteFallback.first && sameSiteFallback.second);
+ string relay_cookie = string("_shibstate_") + state;
+ state = request.getCookie(relay_cookie.c_str());
if (state && *state) {
// URL-decode the value.
char* rscopy = strdup(state);
@@ -407,10 +404,7 @@ void Handler::recoverRelayState(
relayState = rscopy;
free(rscopy);
if (clear) {
- string exp(relay_cookie.second);
- exp += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
- response.setCookie(relay_cookie.first.c_str(), exp.c_str(), HTTPResponse::SAMESITE_NONE,
- sameSiteFallback.first && sameSiteFallback.second);
+ response.setCookie(relay_cookie.c_str(), nullptr, 0, HTTPResponse::SAMESITE_NONE);
}
request.absolutize(relayState);
return;
@@ -661,13 +655,10 @@ void AbstractHandler::preservePostData(
postkey = string(mech.second-3) + ':' + out.string();
}
- pair<string,const char*> shib_cookie = getPostCookieNameProps(application, relayState);
-
- pair<bool,bool> sameSiteFallback = props ? props->getString("sameSiteFallback") : pair<bool,bool>(false, false);
+ string shib_cookie = getPostCookieName(application, relayState);
// Purge any cookies in excess of 25.
int maxCookies = 20,purgedCookies = 0;
- string exp;
// Walk the list of cookies backwards by name.
const map<string,string>& cookies = request.getCookies();
@@ -680,10 +671,7 @@ void AbstractHandler::preservePostData(
}
else {
// We're over the limit, so everything here and older gets cleaned up.
- if (exp.empty())
- exp = string(shib_cookie.second) + "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
- response.setCookie(i->first.c_str(), exp.c_str(), HTTPResponse::SAMESITE_NONE,
- sameSiteFallback.first && sameSiteFallback.second);
+ response.setCookie(i->first.c_str(), nullptr, 0, HTTPResponse::SAMESITE_NONE);
++purgedCookies;
}
}
@@ -693,9 +681,7 @@ void AbstractHandler::preservePostData(
log(SPRequest::SPDebug, string("purged ") + lexical_cast<string>(purgedCookies) + " stale POST preservation cookie(s) from client");
// Set a cookie with key info.
- postkey += shib_cookie.second;
- response.setCookie(shib_cookie.first.c_str(), postkey.c_str(), HTTPResponse::SAMESITE_NONE,
- sameSiteFallback.first && sameSiteFallback.second);
+ response.setCookie(shib_cookie.c_str(), postkey.c_str(), 0, HTTPResponse::SAMESITE_NONE);
}
else {
postData.destroy();
@@ -707,20 +693,15 @@ DDF AbstractHandler::recoverPostData(
const Application& application, const HTTPRequest& request, HTTPResponse& response, const char* relayState
) const
{
- const PropertySet* props = application.getPropertySet("Sessions");
- pair<bool,bool> sameSiteFallback = props ? props->getString("sameSiteFallback") : pair<bool,bool>(false, false);
+ string shib_cookie = getPostCookieName(application, relayState);
// First we need the post recovery cookie.
- pair<string,const char*> shib_cookie = getPostCookieNameProps(application, relayState);
- const char* cookie = request.getCookie(shib_cookie.first.c_str(), sameSiteFallback.first && sameSiteFallback.second);
+ const char* cookie = request.getCookie(shib_cookie.c_str());
if (!cookie || !*cookie)
return DDF();
// Clear the cookie.
- string exp(shib_cookie.second);
- exp += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
- response.setCookie(shib_cookie.first.c_str(), exp.c_str(), HTTPResponse::SAMESITE_NONE,
- sameSiteFallback.first && sameSiteFallback.second);
+ response.setCookie(shib_cookie.c_str(), nullptr, 0, HTTPResponse::SAMESITE_NONE);
// Look for StorageService-backed state of the form "ss:SSID:key".
const char* state = cookie;
@@ -809,21 +790,20 @@ long AbstractHandler::sendPostResponse(
return httpResponse.sendResponse(str);
}
-pair<string,const char*> AbstractHandler::getPostCookieNameProps(const Application& app, const char* relayState) const
+string AbstractHandler::getPostCookieName(const Application& app, const char* relayState) const
{
// Decorates the name of the cookie with the relay state key, if any.
// Doing so gives a better assurance that the recovered data really
// belongs to the relayed request.
- pair<string,const char*> shib_cookie=app.getCookieNameProps("_shibpost_");
if (strstr(relayState, "cookie:") == relayState) {
- shib_cookie.first = string("_shibpost_") + (relayState + 7);
+ return string("_shibpost_") + (relayState + 7);
}
else if (strstr(relayState, "ss:") == relayState) {
const char* pch = strchr(relayState + 3, ':');
if (pch)
- shib_cookie.first = string("_shibpost_") + (pch + 1);
+ return string("_shibpost_") + (pch + 1);
}
- return shib_cookie;
+ return app.getCookieName("_shibpost_");
}
DDF AbstractHandler::getPostData(const Application& application, const HTTPRequest& request) const
diff --git a/shibsp/handler/impl/AdminLogoutInitiator.cpp b/shibsp/handler/impl/AdminLogoutInitiator.cpp
index 2be781b..7a1c5ba 100644
--- a/shibsp/handler/impl/AdminLogoutInitiator.cpp
+++ b/shibsp/handler/impl/AdminLogoutInitiator.cpp
@@ -170,12 +170,12 @@ void AdminLogoutInitiator::receive(DDF& in, ostream& out)
}
// Unpack the request.
- scoped_ptr<HTTPRequest> req(getRequest(in));
+ scoped_ptr<HTTPRequest> req(getRequest(*app, in));
// Set up a response shim.
DDF ret(nullptr);
DDFJanitor jout(ret);
- scoped_ptr<HTTPResponse> resp(getResponse(ret));
+ scoped_ptr<HTTPResponse> resp(getResponse(*app, ret));
// Since we're remoted, the result should either be a throw, which we pass on,
// a false/0 return, which we just return as an empty structure, or a response/redirect,
diff --git a/shibsp/handler/impl/AssertionConsumerService.cpp b/shibsp/handler/impl/AssertionConsumerService.cpp
index a375f25..a896af6 100644
--- a/shibsp/handler/impl/AssertionConsumerService.cpp
+++ b/shibsp/handler/impl/AssertionConsumerService.cpp
@@ -138,12 +138,12 @@ void AssertionConsumerService::receive(DDF& in, ostream& out)
}
// Unpack the request.
- scoped_ptr<HTTPRequest> req(getRequest(in));
+ scoped_ptr<HTTPRequest> req(getRequest(*app, in));
// Wrap a response shim.
DDF ret(nullptr);
DDFJanitor jout(ret);
- scoped_ptr<HTTPResponse> resp(getResponse(ret));
+ scoped_ptr<HTTPResponse> resp(getResponse(*app, ret));
// Since we're remoted, the result should either be a throw, a false/0 return,
// which we just return as an empty structure, or a response/redirect,
@@ -178,7 +178,7 @@ pair<bool,long> AssertionConsumerService::processMessage(
scoped_ptr<XMLObject> msg;
try {
// Decode the message and process it in a protocol-specific way.
- msg.reset(m_decoder->decode(relayState, httpRequest, *(policy.get())));
+ msg.reset(m_decoder->decode(relayState, httpRequest, &httpResponse, *(policy.get())));
if (!msg)
throw BindingException("Failed to decode an SSO protocol response.");
implementProtocol(application, httpRequest, httpResponse, *policy, nullptr, *msg);
diff --git a/shibsp/handler/impl/AssertionLookup.cpp b/shibsp/handler/impl/AssertionLookup.cpp
index 8747f35..280c6a7 100644
--- a/shibsp/handler/impl/AssertionLookup.cpp
+++ b/shibsp/handler/impl/AssertionLookup.cpp
@@ -136,13 +136,13 @@ void AssertionLookup::receive(DDF& in, ostream& out)
}
// Unpack the request.
- scoped_ptr<HTTPRequest> req(getRequest(in));
+ scoped_ptr<HTTPRequest> req(getRequest(*app, in));
//m_log.debug("found %d client certificates", req->getClientCertificates().size());
// Wrap a response shim.
DDF ret(nullptr);
DDFJanitor jout(ret);
- scoped_ptr<HTTPResponse> resp(getResponse(ret));
+ scoped_ptr<HTTPResponse> resp(getResponse(*app, ret));
// Since we're remoted, the result should either be a throw, a false/0 return,
// which we just return as an empty structure, or a response/redirect,
diff --git a/shibsp/handler/impl/ExternalAuthHandler.cpp b/shibsp/handler/impl/ExternalAuthHandler.cpp
index 07ff3bf..82f749f 100644
--- a/shibsp/handler/impl/ExternalAuthHandler.cpp
+++ b/shibsp/handler/impl/ExternalAuthHandler.cpp
@@ -192,7 +192,7 @@ pair<bool,long> ExternalAuth::run(SPRequest& request, bool isHandler) const
headers.push_back("Cookie");
DDF in = wrap(request, &headers);
DDFJanitor jin(in);
- scoped_ptr<HTTPRequest> fakedreq(getRequest(in));
+ scoped_ptr<HTTPRequest> fakedreq(getRequest(request.getApplication(), in));
return processMessage(request.getApplication(), *fakedreq, request, in);
}
else {
@@ -226,12 +226,12 @@ void ExternalAuth::receive(DDF& in, ostream& out)
}
// Unpack the request.
- scoped_ptr<HTTPRequest> req(getRequest(in));
+ scoped_ptr<HTTPRequest> req(getRequest(*app, in));
// Wrap a response shim.
DDF ret(nullptr);
DDFJanitor jout(ret);
- scoped_ptr<HTTPResponse> resp(getResponse(ret));
+ scoped_ptr<HTTPResponse> resp(getResponse(*app, ret));
// Since we're remoted, the result should either be a throw, a false/0 return,
// which we just return as an empty structure, or a response/redirect,
diff --git a/shibsp/handler/impl/LocalLogoutInitiator.cpp b/shibsp/handler/impl/LocalLogoutInitiator.cpp
index 6a48ab2..0eda632 100644
--- a/shibsp/handler/impl/LocalLogoutInitiator.cpp
+++ b/shibsp/handler/impl/LocalLogoutInitiator.cpp
@@ -145,12 +145,12 @@ void LocalLogoutInitiator::receive(DDF& in, ostream& out)
}
// Unpack the request.
- scoped_ptr<HTTPRequest> req(getRequest(in));
+ scoped_ptr<HTTPRequest> req(getRequest(*app, in));
// Set up a response shim.
DDF ret(nullptr);
DDFJanitor jout(ret);
- scoped_ptr<HTTPResponse> resp(getResponse(ret));
+ scoped_ptr<HTTPResponse> resp(getResponse(*app, ret));
Session* session = nullptr;
try {
diff --git a/shibsp/handler/impl/MetadataGenerator.cpp b/shibsp/handler/impl/MetadataGenerator.cpp
index 4b57d80..674f6b1 100644
--- a/shibsp/handler/impl/MetadataGenerator.cpp
+++ b/shibsp/handler/impl/MetadataGenerator.cpp
@@ -415,7 +415,7 @@ void MetadataGenerator::receive(DDF& in, ostream& out)
// Wrap a response shim.
DDF ret(nullptr);
DDFJanitor jout(ret);
- scoped_ptr<HTTPResponse> resp(getResponse(ret));
+ scoped_ptr<HTTPResponse> resp(getResponse(*app, ret));
// Since we're remoted, the result should either be a throw, a false/0 return,
// which we just return as an empty structure, or a response/redirect,
diff --git a/shibsp/handler/impl/RemotedHandler.cpp b/shibsp/handler/impl/RemotedHandler.cpp
index 2b7ba68..2fd941e 100644
--- a/shibsp/handler/impl/RemotedHandler.cpp
+++ b/shibsp/handler/impl/RemotedHandler.cpp
@@ -66,6 +66,7 @@ namespace shibsp {
#endif
public HTTPRequest
{
+ const Application* m_app;
DDF& m_input;
mutable scoped_ptr<CGIParser> m_parser;
mutable vector<XSECCryptoX509*> m_certs;
@@ -74,7 +75,7 @@ namespace shibsp {
mutable gss_name_t m_gssname;
#endif
public:
- RemotedRequest(DDF& input) : m_input(input), m_parser(nullptr)
+ RemotedRequest(const Application* app, DDF& input) : m_app(app), m_input(input), m_parser(nullptr)
#ifdef SHIBSP_HAVE_GSSAPI
, m_gssctx(GSS_C_NO_CONTEXT), m_gssname(GSS_C_NO_NAME)
#endif
@@ -153,19 +154,29 @@ namespace shibsp {
DDF s = m_input["headers"][name];
return s.string() ? s.string() : "";
}
+ const char* getCookie(const char* name) const {
+ pair<bool,bool> sameSiteFallback = pair<bool,bool>(false, false);
+ const PropertySet* props = m_app ? m_app->getPropertySet("Sessions") : nullptr;
+ if (props) {
+ sameSiteFallback = props->getBool("sameSiteFallback");
+ }
+ return HTTPRequest::getCookie(name, sameSiteFallback.first && sameSiteFallback.second);
+ }
};
class SHIBSP_DLLLOCAL RemotedResponse : public virtual HTTPResponse
{
+ const Application* m_app;
DDF& m_output;
public:
- RemotedResponse(DDF& output) : m_output(output) {}
+ RemotedResponse(const Application* app, DDF& output) : m_app(app), m_output(output) {}
virtual ~RemotedResponse() {}
// GenericResponse
long sendResponse(std::istream& inputStream, long status);
// HTTPResponse
+ void setCookie(const char* name, const char* value, time_t expires = 0, samesite_t sameSite = SAMESITE_ABSENT);
void setResponseHeader(const char* name, const char* value, bool replace=false);
long sendRedirect(const char* url);
};
@@ -279,6 +290,44 @@ gss_name_t RemotedRequest::getGSSName() const
}
#endif
+void RemotedResponse::setCookie(const char* name, const char* value, time_t expires, samesite_t sameSite)
+{
+ static const char* defProps="; path=/; HttpOnly";
+ static const char* sslProps="; path=/; secure; HttpOnly";
+
+ const char* cookieProps = defProps;
+ pair<bool,bool> sameSiteFallback = pair<bool,bool>(false, false);
+
+ const PropertySet* props = m_app ? m_app->getPropertySet("Sessions") : nullptr;
+ if (props) {
+ if (sameSite == SAMESITE_NONE) {
+ sameSiteFallback = props->getBool("sameSiteFallback");
+ }
+
+ pair<bool, const char*> p = props->getString("cookieProps");
+ if (p.first) {
+ if (!strcmp(p.second, "https"))
+ cookieProps = sslProps;
+ else if (strcmp(p.second, "http"))
+ cookieProps = p.second;
+ }
+ }
+
+ if (cookieProps) {
+ string decoratedValue(value ? value : "");
+ if (!value) {
+ decoratedValue += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
+ }
+ decoratedValue += cookieProps;
+ HTTPResponse::setCookie(name, decoratedValue.c_str(), expires, sameSite,
+ sameSiteFallback.first && sameSiteFallback.second);
+ }
+ else {
+ HTTPResponse::setCookie(name, value, expires, sameSite,
+ sameSiteFallback.first && sameSiteFallback.second);
+ }
+}
+
long RemotedResponse::sendResponse(std::istream& in, long status)
{
string msg;
@@ -517,8 +566,9 @@ pair<bool,long> RemotedHandler::unwrap(SPRequest& request, DDF& out) const
HTTPRequest* RemotedHandler::getRequest(DDF& in) const
{
+ // TODO: remove in V4
#ifndef SHIBSP_LITE
- return new RemotedRequest(in);
+ return new RemotedRequest(nullptr, in);
#else
throw ConfigurationException("Cannot process message using lite version of shibsp library.");
#endif
@@ -526,8 +576,27 @@ HTTPRequest* RemotedHandler::getRequest(DDF& in) const
HTTPResponse* RemotedHandler::getResponse(DDF& out) const
{
+ // TODO: remove in V4
+#ifndef SHIBSP_LITE
+ return new RemotedResponse(nullptr, out);
+#else
+ throw ConfigurationException("Cannot process message using lite version of shibsp library.");
+#endif
+}
+
+HTTPRequest* RemotedHandler::getRequest(const Application& app, DDF& in) const
+{
+#ifndef SHIBSP_LITE
+ return new RemotedRequest(&app, in);
+#else
+ throw ConfigurationException("Cannot process message using lite version of shibsp library.");
+#endif
+}
+
+HTTPResponse* RemotedHandler::getResponse(const Application& app, DDF& out) const
+{
#ifndef SHIBSP_LITE
- return new RemotedResponse(out);
+ return new RemotedResponse(&app, out);
#else
throw ConfigurationException("Cannot process message using lite version of shibsp library.");
#endif
diff --git a/shibsp/handler/impl/SAML2ArtifactResolution.cpp b/shibsp/handler/impl/SAML2ArtifactResolution.cpp
index 98e1d2d..d7e755c 100644
--- a/shibsp/handler/impl/SAML2ArtifactResolution.cpp
+++ b/shibsp/handler/impl/SAML2ArtifactResolution.cpp
@@ -221,13 +221,13 @@ void SAML2ArtifactResolution::receive(DDF& in, ostream& out)
}
// Unpack the request.
- scoped_ptr<HTTPRequest> req(getRequest(in));
+ scoped_ptr<HTTPRequest> req(getRequest(*app, in));
//m_log.debug("found %d client certificates", req->getClientCertificates().size());
// Wrap a response shim.
DDF ret(nullptr);
DDFJanitor jout(ret);
- scoped_ptr<HTTPResponse> resp(getResponse(ret));
+ scoped_ptr<HTTPResponse> resp(getResponse(*app, ret));
try {
// Since we're remoted, the result should either be a throw, a false/0 return,
@@ -283,7 +283,7 @@ pair<bool,long> SAML2ArtifactResolution::processMessage(const Application& appli
// Decode the message and verify that it's a secured ArtifactResolve request.
string relayState;
- scoped_ptr<XMLObject> msg(m_decoder->decode(relayState, httpRequest, *policy));
+ scoped_ptr<XMLObject> msg(m_decoder->decode(relayState, httpRequest, &httpResponse, *policy));
if (!msg)
throw BindingException("Failed to decode a SAML request.");
const ArtifactResolve* req = dynamic_cast<const ArtifactResolve*>(msg.get());
diff --git a/shibsp/handler/impl/SAML2Logout.cpp b/shibsp/handler/impl/SAML2Logout.cpp
index fb03d1a..e6a6c93 100644
--- a/shibsp/handler/impl/SAML2Logout.cpp
+++ b/shibsp/handler/impl/SAML2Logout.cpp
@@ -244,12 +244,12 @@ void SAML2Logout::receive(DDF& in, ostream& out)
}
// Unpack the request.
- scoped_ptr<HTTPRequest> req(getRequest(in));
+ scoped_ptr<HTTPRequest> req(getRequest(*app, in));
// Wrap a response shim.
DDF ret(nullptr);
DDFJanitor jout(ret);
- scoped_ptr<HTTPResponse> resp(getResponse(ret));
+ scoped_ptr<HTTPResponse> resp(getResponse(*app, ret));
// Since we're remoted, the result should either be a throw, which we pass on,
// a false/0 return, which we just return as an empty structure, or a response/redirect,
@@ -362,7 +362,7 @@ pair<bool,long> SAML2Logout::doRequest(const Application& application, HTTPReque
// Decode the message.
string relayState;
- scoped_ptr<XMLObject> msg(m_decoder->decode(relayState, request, *policy));
+ scoped_ptr<XMLObject> msg(m_decoder->decode(relayState, request, &response, *policy));
const LogoutRequest* logoutRequest = dynamic_cast<LogoutRequest*>(msg.get());
if (logoutRequest) {
if (!policy->isAuthenticated())
diff --git a/shibsp/handler/impl/SAML2LogoutInitiator.cpp b/shibsp/handler/impl/SAML2LogoutInitiator.cpp
index 1c09539..02cb220 100644
--- a/shibsp/handler/impl/SAML2LogoutInitiator.cpp
+++ b/shibsp/handler/impl/SAML2LogoutInitiator.cpp
@@ -250,12 +250,12 @@ void SAML2LogoutInitiator::receive(DDF& in, ostream& out)
}
// Unpack the request.
- scoped_ptr<HTTPRequest> req(getRequest(in));
+ scoped_ptr<HTTPRequest> req(getRequest(*app, in));
// Set up a response shim.
DDF ret(nullptr);
DDFJanitor jout(ret);
- scoped_ptr<HTTPResponse> resp(getResponse(ret));
+ scoped_ptr<HTTPResponse> resp(getResponse(*app, ret));
Session* session = nullptr;
try {
diff --git a/shibsp/handler/impl/SAML2NameIDMgmt.cpp b/shibsp/handler/impl/SAML2NameIDMgmt.cpp
index 68cb35f..2e8956a 100644
--- a/shibsp/handler/impl/SAML2NameIDMgmt.cpp
+++ b/shibsp/handler/impl/SAML2NameIDMgmt.cpp
@@ -225,12 +225,12 @@ void SAML2NameIDMgmt::receive(DDF& in, ostream& out)
}
// Unpack the request.
- scoped_ptr<HTTPRequest> req(getRequest(in));
+ scoped_ptr<HTTPRequest> req(getRequest(*app, in));
// Wrap a response shim.
DDF ret(nullptr);
DDFJanitor jout(ret);
- scoped_ptr<HTTPResponse> resp(getResponse(ret));
+ scoped_ptr<HTTPResponse> resp(getResponse(*app, ret));
// Since we're remoted, the result should either be a throw, which we pass on,
// a false/0 return, which we just return as an empty structure, or a response/redirect,
@@ -261,7 +261,7 @@ pair<bool,long> SAML2NameIDMgmt::doRequest(const Application& application, HTTPR
// Decode the message.
string relayState;
- scoped_ptr<XMLObject> msg(m_decoder->decode(relayState, request, *policy));
+ scoped_ptr<XMLObject> msg(m_decoder->decode(relayState, request, &response, *policy));
const ManageNameIDRequest* mgmtRequest = dynamic_cast<ManageNameIDRequest*>(msg.get());
if (mgmtRequest) {
if (!policy->isAuthenticated())
diff --git a/shibsp/handler/impl/SAML2SessionInitiator.cpp b/shibsp/handler/impl/SAML2SessionInitiator.cpp
index 8c2d0cc..ecde0b1 100644
--- a/shibsp/handler/impl/SAML2SessionInitiator.cpp
+++ b/shibsp/handler/impl/SAML2SessionInitiator.cpp
@@ -529,7 +529,7 @@ void SAML2SessionInitiator::receive(DDF& in, ostream& out)
DDFJanitor jout(ret);
// Wrap the outgoing object with a Response facade.
- scoped_ptr<HTTPResponse> http(getResponse(ret));
+ scoped_ptr<HTTPResponse> http(getResponse(*app, ret));
auto_ptr_XMLCh index(in["acsIndex"].string());
auto_ptr_XMLCh bind(in["acsBinding"].string());
diff --git a/shibsp/handler/impl/Shib1SessionInitiator.cpp b/shibsp/handler/impl/Shib1SessionInitiator.cpp
index c4aed4c..cbdd7a7 100644
--- a/shibsp/handler/impl/Shib1SessionInitiator.cpp
+++ b/shibsp/handler/impl/Shib1SessionInitiator.cpp
@@ -253,7 +253,7 @@ void Shib1SessionInitiator::receive(DDF& in, ostream& out)
DDFJanitor jout(ret);
// Wrap the outgoing object with a Response facade.
- scoped_ptr<HTTPResponse> http(getResponse(ret));
+ scoped_ptr<HTTPResponse> http(getResponse(*app, ret));
string relayState(in["RelayState"].string() ? in["RelayState"].string() : "");
diff --git a/shibsp/handler/impl/StatusHandler.cpp b/shibsp/handler/impl/StatusHandler.cpp
index 1f27caf..45851cc 100644
--- a/shibsp/handler/impl/StatusHandler.cpp
+++ b/shibsp/handler/impl/StatusHandler.cpp
@@ -363,8 +363,8 @@ void StatusHandler::receive(DDF& in, ostream& out)
// Wrap a response shim.
DDF ret(nullptr);
DDFJanitor jout(ret);
- scoped_ptr<HTTPRequest> req(getRequest(in));
- scoped_ptr<HTTPResponse> resp(getResponse(ret));
+ scoped_ptr<HTTPRequest> req(getRequest(*app, in));
+ scoped_ptr<HTTPResponse> resp(getResponse(*app, ret));
// Since we're remoted, the result should either be a throw, a false/0 return,
// which we just return as an empty structure, or a response/redirect,
diff --git a/shibsp/impl/StorageServiceSessionCache.cpp b/shibsp/impl/StorageServiceSessionCache.cpp
index 3f86880..897efd8 100644
--- a/shibsp/impl/StorageServiceSessionCache.cpp
+++ b/shibsp/impl/StorageServiceSessionCache.cpp
@@ -284,11 +284,7 @@ string SSCache::active(const Application& app, const HTTPRequest& request)
return session_id;
}
- const PropertySet* props = app.getPropertySet("Sessions");
- pair<bool,bool> sameSiteFallback = props ? props->getBool("sameSiteFallback") : pair<bool,bool>(false, false);
-
- pair<string, const char*> shib_cookie = app.getCookieNameProps("_shibsession_");
- const char* session_id = request.getCookie(shib_cookie.first.c_str(), sameSiteFallback.first && sameSiteFallback.second);
+ const char* session_id = request.getCookie(app.getCookieName("_shibsession_").c_str());
return (session_id ? session_id : "");
}
@@ -559,25 +555,9 @@ void SSCache::insert(
httpResponse.setResponseHeader(m_outboundHeader.c_str(), key.get());
time_t cookieLifetime = 0;
- pair<string,const char*> shib_cookie = app.getCookieNameProps("_shibsession_", &cookieLifetime);
- string k(key.get());
- k += shib_cookie.second;
-
- if (cookieLifetime > 0) {
- cookieLifetime += now;
-#ifndef HAVE_GMTIME_R
- ptime=gmtime(&cookieLifetime);
-#else
- ptime=gmtime_r(&cookieLifetime,&res);
-#endif
- char cookietimebuf[64];
- strftime(cookietimebuf,64,"; expires=%a, %d %b %Y %H:%M:%S GMT",ptime);
- k += cookietimebuf;
- }
-
- pair<bool,HTTPResponse::samesite_t> sameSitePolicy = getSameSitePolicy(app);
-
- httpResponse.setCookie(shib_cookie.first.c_str(), k.c_str(), sameSitePolicy.second, sameSitePolicy.first);
+ string shib_cookie = app.getCookieName("_shibsession_", &cookieLifetime);
+ HTTPResponse::samesite_t sameSitePolicy = getSameSitePolicy(app);
+ httpResponse.setCookie(shib_cookie.c_str(), key.get(), cookieLifetime, sameSitePolicy);
sessionID = key.get();
// See if we need to persist the session data itself to a cookie for cross-node recovery.
@@ -591,8 +571,8 @@ void SSCache::persist(
HTTPResponse& httpResponse,
DDF& session,
time_t expires,
- pair<bool,HTTPResponse::samesite_t>& sameSitePolicy
-) const
+ HTTPResponse::samesite_t sameSitePolicy
+ ) const
{
#ifdef _DEBUG
xmltooling::NDC ndc("persist");
@@ -631,21 +611,8 @@ void SSCache::persist(
sealed = XMLToolingConfig::getConfig().getURLEncoder()->encode(sealed.c_str());
time_t cookieLifetime;
- pair<string,const char*> shib_cookie = app.getCookieNameProps("_shibsealed_", &cookieLifetime);
- sealed += shib_cookie.second;
- if (cookieLifetime > 0) {
- cookieLifetime += time(nullptr);
-#ifndef HAVE_GMTIME_R
- struct tm* ptime = gmtime(&cookieLifetime);
-#else
- struct tm res;
- struct tm* ptime = gmtime_r(&cookieLifetime, &res);
-#endif
- char cookietimebuf[64];
- strftime(cookietimebuf, 64, "; expires=%a, %d %b %Y %H:%M:%S GMT", ptime);
- sealed += cookietimebuf;
- }
- httpResponse.setCookie(shib_cookie.first.c_str(), sealed.c_str(), sameSitePolicy.second, sameSitePolicy.first);
+ string shib_cookie = app.getCookieName("_shibsealed_", &cookieLifetime);
+ httpResponse.setCookie(shib_cookie.c_str(), sealed.c_str(), cookieLifetime, sameSitePolicy);
}
catch (const std::exception& e) {
m_log.error("failed to wrap session (%s) with DataSealer: %s", session.name(), e.what());
@@ -908,28 +875,24 @@ LogoutEvent* SSCache::newLogoutEvent(const Application& app) const
#endif
-pair<bool,HTTPResponse::samesite_t> SSCache::getSameSitePolicy(const Application& app) const
+HTTPResponse::samesite_t SSCache::getSameSitePolicy(const Application& app) const
{
- HTTPResponse::samesite_t ss = HTTPResponse::SAMESITE_ABSENT;
- pair<bool,bool> sameSiteFallback = pair<bool,bool>(false, false);
-
const PropertySet* props = app.getPropertySet("Sessions");
if (props) {
- sameSiteFallback = props->getBool("sameSiteFallback");
pair<bool,const char*> sameSiteSession = props->getString("sameSiteSession");
if (sameSiteSession.first) {
if (!strcmp(sameSiteSession.second, "None")) {
- ss = HTTPResponse::SAMESITE_NONE;
+ return HTTPResponse::SAMESITE_NONE;
}
else if (!strcmp(sameSiteSession.second, "Lax")) {
- ss = HTTPResponse::SAMESITE_LAX;
+ return HTTPResponse::SAMESITE_LAX;
}
else if (!strcmp(sameSiteSession.second, "Strict")) {
- ss = HTTPResponse::SAMESITE_STRICT;
+ return HTTPResponse::SAMESITE_STRICT;
}
}
}
- return pair<bool,HTTPResponse::samesite_t>(sameSiteFallback.first && sameSiteFallback.second, ss);
+ return HTTPResponse::SAMESITE_ABSENT;
}
Session* SSCache::_find(const Application& app, const char* key, const char* recovery, const char* client_addr, time_t* timeout)
@@ -1126,10 +1089,8 @@ Session* SSCache::find(const Application& app, HTTPRequest& request, const char*
if (id.empty())
return nullptr;
- pair<bool,HTTPResponse::samesite_t> sameSitePolicy = getSameSitePolicy(app);
-
- pair<string, const char*> shib_cookie = app.getCookieNameProps("_shibsealed_");
- const char* c = request.getCookie(shib_cookie.first.c_str(), sameSitePolicy.first);
+ HTTPResponse::samesite_t sameSitePolicy = getSameSitePolicy(app);
+ const char* c = request.getCookie(app.getCookieName("_shibsealed_").c_str());
try {
Session* session = _find(app, id.c_str(), c, client_addr, timeout);
@@ -1140,12 +1101,8 @@ Session* SSCache::find(const Application& app, HTTPRequest& request, const char*
if (response) {
if (!m_outboundHeader.empty())
response->setResponseHeader(m_outboundHeader.c_str(), nullptr);
- pair<string,const char*> shib_cookie = app.getCookieNameProps("_shibsession_");
- string exp(shib_cookie.second);
- exp += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
- response->setCookie(shib_cookie.first.c_str(), exp.c_str(), sameSitePolicy.second, sameSitePolicy.first);
- shib_cookie = app.getCookieNameProps("_shibsealed_");
- response->setCookie(shib_cookie.first.c_str(), exp.c_str(), sameSitePolicy.second, sameSitePolicy.first);
+ response->setCookie(app.getCookieName("_shibsession_").c_str(), nullptr, 0, sameSitePolicy);
+ response->setCookie(app.getCookieName("_shibsealed_").c_str(), nullptr, 0, sameSitePolicy);
}
}
catch (const std::exception&) {
@@ -1153,12 +1110,8 @@ Session* SSCache::find(const Application& app, HTTPRequest& request, const char*
if (response) {
if (!m_outboundHeader.empty())
response->setResponseHeader(m_outboundHeader.c_str(), nullptr);
- pair<string,const char*> shib_cookie = app.getCookieNameProps("_shibsession_");
- string exp(shib_cookie.second);
- exp += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
- response->setCookie(shib_cookie.first.c_str(), exp.c_str(), sameSitePolicy.second, sameSitePolicy.first);
- shib_cookie = app.getCookieNameProps("_shibsealed_");
- response->setCookie(shib_cookie.first.c_str(), exp.c_str(), sameSitePolicy.second, sameSitePolicy.first);
+ response->setCookie(app.getCookieName("_shibsession_").c_str(), nullptr, 0, sameSitePolicy);
+ response->setCookie(app.getCookieName("_shibsealed_").c_str(), nullptr, 0, sameSitePolicy);
}
throw;
}
@@ -1292,14 +1245,12 @@ void SSCache::remove(const Application& app, const HTTPRequest& request, HTTPRes
xmltooling::NDC ndc("remove");
#endif
string session_id;
- pair<string,const char*> shib_cookie = app.getCookieNameProps("_shibsession_");
-
- pair<bool,HTTPResponse::samesite_t> sameSitePolicy = getSameSitePolicy(app);
+ string shib_cookie = app.getCookieName("_shibsession_");
if (!m_inboundHeader.empty())
session_id = request.getHeader(m_inboundHeader.c_str());
if (session_id.empty()) {
- const char* c = request.getCookie(shib_cookie.first.c_str(), sameSitePolicy.first);
+ const char* c = request.getCookie(shib_cookie.c_str());
if (c && *c)
session_id = c;
}
@@ -1308,12 +1259,9 @@ void SSCache::remove(const Application& app, const HTTPRequest& request, HTTPRes
if (response) {
if (!m_outboundHeader.empty())
response->setResponseHeader(m_outboundHeader.c_str(), nullptr);
- string exp(shib_cookie.second);
- exp += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
- response->setCookie(shib_cookie.first.c_str(), exp.c_str(), sameSitePolicy.second, sameSitePolicy.first);
-
- shib_cookie = app.getCookieNameProps("_shibsealed_");
- response->setCookie(shib_cookie.first.c_str(), exp.c_str(), sameSitePolicy.second, sameSitePolicy.first);
+ HTTPResponse::samesite_t sameSitePolicy = getSameSitePolicy(app);
+ response->setCookie(shib_cookie.c_str(), nullptr, 0, sameSitePolicy);
+ response->setCookie(app.getCookieName("_shibsealed_").c_str(), nullptr, 0, sameSitePolicy);
}
remove(app, session_id.c_str(), revocationExp);
}
diff --git a/shibsp/impl/StorageServiceSessionCache.h b/shibsp/impl/StorageServiceSessionCache.h
index 09b3430..d447018 100644
--- a/shibsp/impl/StorageServiceSessionCache.h
+++ b/shibsp/impl/StorageServiceSessionCache.h
@@ -165,7 +165,7 @@ namespace shibsp {
// handle potentially inexact address comparisons
bool compareAddresses(const char* client_addr, const char* session_addr) const;
- std::pair<bool,xmltooling::HTTPResponse::samesite_t> getSameSitePolicy(const Application& app) const;
+ xmltooling::HTTPResponse::samesite_t getSameSitePolicy(const Application& app) const;
// management of buffered sessions
void dormant(const char* key);
@@ -178,7 +178,7 @@ namespace shibsp {
xmltooling::HTTPResponse& httpResponse,
DDF& session,
time_t expires,
- std::pair<bool,xmltooling::HTTPResponse::samesite_t>& sameSitePolicy
+ xmltooling::HTTPResponse::samesite_t sameSitePolicy
) const;
#endif
bool recover(const Application& app, const char* key, const char* data);
diff --git a/shibsp/impl/XMLApplication.cpp b/shibsp/impl/XMLApplication.cpp
index 0355d1f..20a9d6d 100644
--- a/shibsp/impl/XMLApplication.cpp
+++ b/shibsp/impl/XMLApplication.cpp
@@ -38,6 +38,7 @@
#include <xercesc/util/XMLStringTokenizer.hpp>
#include <xmltooling/XMLToolingConfig.h>
#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/XMLConstants.h>
#include <xmltooling/util/XMLHelper.h>
#ifndef SHIBSP_LITE
@@ -82,6 +83,7 @@ namespace {
static const XMLCh _Audience[] = UNICODE_LITERAL_8(A,u,d,i,e,n,c,e);
static const XMLCh Binding[] = UNICODE_LITERAL_7(B,i,n,d,i,n,g);
static const XMLCh Channel[]= UNICODE_LITERAL_7(C,h,a,n,n,e,l);
+ static const XMLCh checkCorrelation[] = UNICODE_LITERAL_16(c,h,e,c,k,C,o,r,r,e,l,a,t,i,o,n);
static const XMLCh _CredentialResolver[] = UNICODE_LITERAL_18(C,r,e,d,e,n,t,i,a,l,R,e,s,o,l,v,e,r);
static const XMLCh _default[] = UNICODE_LITERAL_7(d,e,f,a,u,l,t);
static const XMLCh ExternalApplicationOverrides[] = UNICODE_LITERAL_28(E,x,t,e,r,n,a,l,A,p,p,l,i,c,a,t,i,o,n,O,v,e,r,r,i,d,e,s);
@@ -556,6 +558,9 @@ void XMLApplication::doHandlers(const ProtocolProvider* pp, const DOMElement* e,
child = XMLHelper::getNextSiblingElement(child);
continue;
}
+ // Somewhat icky; we disable request/response correlation by default by injecting an attribute
+ // to be picked up by the auto-added BEARER policy rule that's wrapped around this same element.
+ child->setAttributeNS(nullptr, checkCorrelation, xmlconstants::XML_ZERO);
handler.reset(
conf.AssertionConsumerServiceManager.newPlugin(bindprop.c_str(), pair<const DOMElement*,const char*>(child, getId()), m_deprecationSupport)
);
@@ -755,6 +760,10 @@ void XMLApplication::doSSO(const ProtocolProvider& pp, set<string>& protocols, D
if (idprop.first && pathprop.first) {
DOMElement* acsdom = e->getOwnerDocument()->createElementNS(samlconstants::SAML20MD_NS, _AssertionConsumerService);
+ // Somewhat icky; we disable request/response correlation by default by injecting an attribute
+ // to be picked up by the auto-added BEARER policy rule that's wrapped around this same element.
+ acsdom->setAttributeNS(nullptr, checkCorrelation, xmlconstants::XML_ZERO);
+
// Copy in any attributes from the <SSO> element so they can be accessed as properties in the ACS handler,
// since the handlers aren't attached to the SSO element.
for (XMLSize_t p = 0; p < ssopropslen; ++p) {
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list