<value>org.eclipse.cdt.core.MakeErrorParser;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.VCErrorParser;</value>\r
</dictionary>\r
<dictionary>\r
- <key>org.eclipse.cdt.make.core.enableAutoBuild</key>\r
- <value>false</value>\r
- </dictionary>\r
- <dictionary>\r
<key>org.eclipse.cdt.make.core.environment</key>\r
<value></value>\r
</dictionary>\r
<dictionary>\r
- <key>org.eclipse.cdt.make.core.enableFullBuild</key>\r
- <value>true</value>\r
+ <key>org.eclipse.cdt.make.core.enableAutoBuild</key>\r
+ <value>false</value>\r
</dictionary>\r
<dictionary>\r
<key>org.eclipse.cdt.make.core.build.target.inc</key>\r
<value>all</value>\r
</dictionary>\r
<dictionary>\r
- <key>org.eclipse.cdt.make.core.enabledIncrementalBuild</key>\r
+ <key>org.eclipse.cdt.make.core.enableFullBuild</key>\r
<value>true</value>\r
</dictionary>\r
<dictionary>\r
- <key>org.eclipse.cdt.make.core.build.target.clean</key>\r
- <value>clean</value>\r
+ <key>org.eclipse.cdt.make.core.enabledIncrementalBuild</key>\r
+ <value>true</value>\r
</dictionary>\r
<dictionary>\r
<key>org.eclipse.cdt.make.core.build.command</key>\r
<value>make</value>\r
</dictionary>\r
<dictionary>\r
+ <key>org.eclipse.cdt.make.core.build.target.clean</key>\r
+ <value>clean</value>\r
+ </dictionary>\r
+ <dictionary>\r
<key>org.eclipse.cdt.make.core.enableCleanBuild</key>\r
<value>true</value>\r
</dictionary>\r
SAMLConfig.h
samlbindinclude_HEADERS = \
+ binding/ArtifactMap.h \
+ binding/MessageEncoder.h \
binding/SAMLArtifact.h
encinclude_HEADERS = \
saml1/core/Protocols.h
saml1bindinclude_HEADERS = \
+ saml1/binding/SAML1ArtifactEncoder.h \
+ saml1/binding/SAML1POSTEncoder.h \
saml1/binding/SAMLArtifactType0001.h \
saml1/binding/SAMLArtifactType0002.h
libsaml_la_SOURCES = \
SAMLConfig.cpp \
+ binding/impl/ArtifactMap.cpp \
binding/impl/SAMLArtifact.cpp \
saml1/core/impl/AssertionsImpl.cpp \
saml1/core/impl/AssertionsSchemaValidators.cpp \
saml1/core/impl/ProtocolsImpl.cpp \
saml1/core/impl/ProtocolsSchemaValidators.cpp \
+ saml1/binding/impl/SAML1ArtifactEncoder.cpp \
+ saml1/binding/impl/SAML1POSTEncoder.cpp \
saml1/binding/impl/SAMLArtifactType0001.cpp \
saml1/binding/impl/SAMLArtifactType0002.cpp \
saml2/core/impl/Assertions20Impl.cpp \
#include "internal.h"
#include "exceptions.h"
#include "SAMLConfig.h"
+#include "binding/MessageEncoder.h"
#include "binding/SAMLArtifact.h"
#include "saml1/core/Assertions.h"
#include "saml1/core/Protocols.h"
DECL_EXCEPTION_FACTORY(ArtifactException,opensaml);
DECL_EXCEPTION_FACTORY(MetadataFilterException,opensaml::saml2md);
+DECL_EXCEPTION_FACTORY(BindingException,opensaml);
namespace opensaml {
SAMLInternalConfig g_config;
REGISTER_EXCEPTION_FACTORY(ArtifactException,opensaml);
REGISTER_EXCEPTION_FACTORY(MetadataFilterException,opensaml::saml2md);
+ REGISTER_EXCEPTION_FACTORY(BindingException,opensaml);
+ registerMessageEncoders();
registerSAMLArtifacts();
saml1::registerAssertionClasses();
saml1p::registerProtocolClasses();
saml2::AssertionSchemaValidators.destroyValidators();
saml2md::MetadataSchemaValidators.destroyValidators();
- SAMLArtifactManager.deregisterFactories();
+ TrustEngineManager.deregisterFactories();
MetadataFilterManager.deregisterFactories();
MetadataProviderManager.deregisterFactories();
- TrustEngineManager.deregisterFactories();
+ SAMLArtifactManager.deregisterFactories();
+ MessageEncoderManager.deregisterFactories();
+
+ delete m_artifactMap;
+ m_artifactMap = NULL;
if (termXMLTooling) {
XMLToolingConfig::getConfig().term();
#define __saml_config_h__\r
\r
#include <saml/base.h>\r
+#include <saml/binding/ArtifactMap.h>\r
\r
#include <xmltooling/PluginManager.h>\r
#include <xmltooling/XMLToolingConfig.h>\r
*/\r
namespace opensaml {\r
\r
+ class SAML_API MessageEncoder;\r
+ class SAML_API MessageDecoder;\r
class SAML_API SAMLArtifact;\r
class SAML_API TrustEngine;\r
\r
virtual void term(bool termXMLTooling=true)=0;\r
\r
/**\r
+ * Sets the global ArtifactMap instance.\r
+ * This method must be externally synchronized with any code that uses the object.\r
+ * Any previously set object is destroyed.\r
+ * \r
+ * @param artifactMap new ArtifactMap instance to store\r
+ */\r
+ void setArtifactMap(ArtifactMap* artifactMap) {\r
+ delete m_artifactMap;\r
+ m_artifactMap = artifactMap;\r
+ }\r
+ \r
+ /**\r
+ * Returns the global ArtifactMap instance.\r
+ * \r
+ * @return global ArtifactMap\r
+ */\r
+ ArtifactMap* getArtifactMap() const {\r
+ return m_artifactMap;\r
+ }\r
+ \r
+ /**\r
* Generate random information using the underlying security library\r
* \r
* @param buf buffer for the information\r
* @return SHA-1 hash of the data\r
*/\r
virtual std::string hashSHA1(const char* s, bool toHex=false)=0;\r
- \r
+\r
/**\r
- * Manages factories for MetadataProvider plugins.\r
+ * Manages factories for MessageDecoder plugins.\r
*/\r
- xmltooling::PluginManager<saml2md::MetadataProvider,const DOMElement*> MetadataProviderManager;\r
- \r
+ xmltooling::PluginManager<MessageDecoder,const DOMElement*> MessageDecoderManager;\r
+\r
/**\r
- * Manages factories for MetadataFilter plugins.\r
+ * Manages factories for MessageEncoder plugins.\r
*/\r
- xmltooling::PluginManager<saml2md::MetadataFilter,const DOMElement*> MetadataFilterManager;\r
+ xmltooling::PluginManager<MessageEncoder,const DOMElement*> MessageEncoderManager; \r
\r
/**\r
* Manages factories for SAMLArtifact plugins.\r
*/\r
xmltooling::PluginManager<TrustEngine,const DOMElement*> TrustEngineManager;\r
\r
+ /**\r
+ * Manages factories for MetadataProvider plugins.\r
+ */\r
+ xmltooling::PluginManager<saml2md::MetadataProvider,const DOMElement*> MetadataProviderManager;\r
+ \r
+ /**\r
+ * Manages factories for MetadataFilter plugins.\r
+ */\r
+ xmltooling::PluginManager<saml2md::MetadataFilter,const DOMElement*> MetadataFilterManager;\r
+\r
protected:\r
- SAMLConfig() {}\r
+ SAMLConfig() : m_artifactMap(NULL) {}\r
+ \r
+ /** Global ArtifactMap instance for use by artifact-related functions. */\r
+ ArtifactMap* m_artifactMap;\r
};\r
\r
#if defined (_MSC_VER)\r
--- /dev/null
+/*\r
+ * Copyright 2001-2006 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * @file saml/binding/ArtifactMap.h\r
+ * \r
+ * Helper class for SAMLArtifact mapping and retrieval.\r
+ */\r
+\r
+#ifndef __saml_artmap_h__\r
+#define __saml_artmap_h__\r
+\r
+#include <saml/base.h>\r
+#include <xmltooling/XMLObject.h>\r
+#include <xmltooling/util/StorageService.h>\r
+#include <xmltooling/util/Threads.h>\r
+\r
+namespace opensaml {\r
+\r
+ class SAML_API SAMLArtifact;\r
+ class SAML_DLLLOCAL ArtifactMappings;\r
+ \r
+ /**\r
+ * Helper class for SAMLArtifact mapping and retrieval.\r
+ */\r
+ class SAML_API ArtifactMap\r
+ {\r
+ MAKE_NONCOPYABLE(ArtifactMap);\r
+ public:\r
+ \r
+ /**\r
+ * Creates a map on top of a particular storage service context, or in-memory.\r
+ * \r
+ * @param storage pointer to a StorageService, or NULL to keep map in memory\r
+ * @param context optional label for storage context\r
+ * @param artifactTTL time to live value, determines how long artifact remains valid\r
+ */\r
+ ArtifactMap(xmltooling::StorageService* storage=NULL, const char* context=NULL, int artifactTTL=180);\r
+\r
+ virtual ~ArtifactMap();\r
+ \r
+ /**\r
+ * Associates XML content with an artifact and optionally a specific relying party.\r
+ * Specifying no relying party means that the first attempt to resolve the artifact\r
+ * will succeed. The XML content cannot have a parent object, and any existing references\r
+ * to the content will be invalidated.\r
+ * \r
+ * @param content the XML content to map to an artifact\r
+ * @param artifact the artifact representing the XML content\r
+ * @param relyingParty entityID of the party authorized to resolve the artifact\r
+ * @return the generated artifact\r
+ */\r
+ virtual void storeContent(xmltooling::XMLObject* content, const SAMLArtifact* artifact, const char* relyingParty=NULL);\r
+ \r
+ /**\r
+ * Retrieves the XML content represented by the artifact. The identity of the\r
+ * relying party can be supplied, if known. If the wrong party tries to resolve\r
+ * an artifact, an exception will be thrown and the mapping will be removed.\r
+ * The caller is responsible for freeing the XML content returned.\r
+ * \r
+ * @param artifact the artifact representing the XML content\r
+ * @param relyingParty entityID of the party trying to resolve the artifact\r
+ * @return the XML content\r
+ */\r
+ virtual xmltooling::XMLObject* retrieveContent(const SAMLArtifact* artifact, const char* relyingParty=NULL);\r
+\r
+ private:\r
+ xmltooling::StorageService* m_storage;\r
+ std::string m_context;\r
+ ArtifactMappings* m_mappings;\r
+ int m_artifactTTL;\r
+ };\r
+};\r
+\r
+#endif /* __saml_artmap_h__ */\r
--- /dev/null
+/*\r
+ * Copyright 2001-2006 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * @file saml/binding/MessageEncoder.h\r
+ * \r
+ * Interface to SAML protocol binding message encoders. \r
+ */\r
+\r
+#ifndef __saml_encoder_h__\r
+#define __saml_encoder_h__\r
+\r
+#include <saml/base.h>\r
+\r
+#include <map>\r
+#include <string>\r
+#include <xmltooling/XMLObject.h>\r
+#include <xmltooling/signature/CredentialResolver.h>\r
+#include <xmltooling/util/StorageService.h>\r
+\r
+namespace opensaml {\r
+\r
+ class SAML_API SAMLArtifact;\r
+ namespace saml2p {\r
+ class SAML_API SAML2Artifact;\r
+ };\r
+\r
+ /**\r
+ * Interface to SAML protocol binding message encoders.\r
+ */\r
+ class SAML_API MessageEncoder\r
+ {\r
+ MAKE_NONCOPYABLE(MessageEncoder);\r
+ public:\r
+ virtual ~MessageEncoder() {}\r
+\r
+ /**\r
+ * Interface to caller-supplied URL-encoding mechanism.\r
+ * \r
+ * Since URL-encoding is not canonical, it's important that the same\r
+ * encoder is used during some binding-specific signature operations.\r
+ */\r
+ class SAML_API URLEncoder {\r
+ MAKE_NONCOPYABLE(URLEncoder);\r
+ protected:\r
+ URLEncoder() {}\r
+ public:\r
+ virtual ~URLEncoder() {}\r
+ \r
+ /**\r
+ * Produce a URL-safe but equivalent version of the input string.\r
+ * \r
+ * @param s input string to encode\r
+ * @return a string object containing the result of encoding the input\r
+ */\r
+ virtual std::string encode(const char* s) const=0;\r
+ };\r
+ \r
+ /**\r
+ * Provides a URLEncoder implementation for the MessageEncoder to use.\r
+ * The implementation's lifetime must be longer than the lifetime of this object.\r
+ * This method must be externally synchronized. \r
+ * \r
+ * @param urlEncoder a URLEncoder implementation to use\r
+ */\r
+ void setURLEncoder(const URLEncoder* urlEncoder) {\r
+ m_urlEncoder = urlEncoder;\r
+ }\r
+\r
+ /**\r
+ * Interface to caller-supplied artifact generation mechanism.\r
+ * \r
+ * Generating an artifact for storage and retrieval requires knowledge of\r
+ * the sender's SourceID (or sometimes SourceLocation), and the relying party's\r
+ * preferred artifact type. This information can be supplied using whatever\r
+ * configuration or defaults are appropriate for the SAML application.\r
+ * An ArtifactMap implementation will invoke the supplied generator interface\r
+ * when it requires an artifact be created.\r
+ */\r
+ class SAML_API ArtifactGenerator {\r
+ MAKE_NONCOPYABLE(ArtifactGenerator);\r
+ protected:\r
+ ArtifactGenerator() {}\r
+ public:\r
+ virtual ~ArtifactGenerator() {}\r
+ \r
+ /**\r
+ * Generate a SAML 1.x artifact suitable for consumption by the relying party.\r
+ * \r
+ * @param relyingParty the party that will recieve the artifact\r
+ * @return a SAML 1.x artifact with a random assertion handle\r
+ */\r
+ virtual SAMLArtifact* generateSAML1Artifact(const char* relyingParty) const=0;\r
+\r
+ /**\r
+ * Generate a SAML 2.0 artifact suitable for consumption by the relying party.\r
+ * \r
+ * @param relyingParty the party that will recieve the artifact\r
+ * @return a SAML 2.0 artifact with a random message handle\r
+ */\r
+ virtual saml2p::SAML2Artifact* generateSAML2Artifact(const char* relyingParty) const=0;\r
+ };\r
+\r
+ /**\r
+ * Provides an ArtifactGenerator implementation for the MessageEncoder to use.\r
+ * The implementation's lifetime must be longer than the lifetime of this object. \r
+ * This method must be externally synchronized. \r
+ * \r
+ * @param artifactGenerator an ArtifactGenerator implementation to use\r
+ */\r
+ void setArtifactGenerator(ArtifactGenerator* artifactGenerator) {\r
+ m_artifactGenerator = artifactGenerator;\r
+ }\r
+ \r
+ /**\r
+ * Encodes an XML object/message into a set of binding-specific data "fields".\r
+ * The XML content cannot have a parent object, and any existing references to\r
+ * the content will be invalidated if the encode method returns successfully.\r
+ * \r
+ * If a CredentialResolver is supplied, the message is also signed in a\r
+ * binding-specific manner. The CredentialResolver <strong>MUST</strong>\r
+ * be locked by the caller. \r
+ * \r
+ * <p>An embedded URLEncoder instance may be required by some bindings\r
+ * in order to produce predictable signature input.\r
+ * \r
+ * <p>Artifact-based bindings require an ArtifactGenerator be set to\r
+ * produce an artifact suitable for the intended recipient.\r
+ * \r
+ * <p>Note that the name/value pairs resulting from the encoding operation are\r
+ * <strong>NOT</strong> URL-encoded or otherwise transformed. It is the caller's\r
+ * responsibility to apply any necessary encoding when preparing the data for\r
+ * transport.\r
+ * \r
+ * @param outputFields name/value pairs containing the results of encoding the message\r
+ * @param xmlObject XML object/message to encode\r
+ * @param recipientID optional entityID of message recipient\r
+ * @param relayState optional RelayState value to accompany message\r
+ * @param credResolver optional CredentialResolver instance to supply signing material\r
+ * @param sigAlgorithm optional signature algorithm identifier\r
+ */\r
+ virtual void encode(\r
+ std::map<std::string,std::string>& outputFields,\r
+ xmltooling::XMLObject* xmlObject,\r
+ const char* recipientID=NULL,\r
+ const char* relayState=NULL,\r
+ const xmlsignature::CredentialResolver* credResolver=NULL,\r
+ const XMLCh* sigAlgorithm=NULL\r
+ ) const=0;\r
+\r
+ protected:\r
+ MessageEncoder() : m_urlEncoder(NULL), m_artifactGenerator(NULL) {}\r
+ \r
+ /** Pointer to a URLEncoder implementation. */\r
+ const URLEncoder* m_urlEncoder;\r
+ \r
+ /** Pointer to an ArtifactGenerator implementation. */\r
+ const ArtifactGenerator* m_artifactGenerator;\r
+ };\r
+\r
+ /**\r
+ * Registers MessageEncoder plugins into the runtime.\r
+ */\r
+ void SAML_API registerMessageEncoders();\r
+\r
+ /** MessageEncoder for SAML 1.x Browser/Artifact "binding" (really part of profile) */\r
+ #define SAML1_ARTIFACT_ENCODER "org.opensaml.saml1.binding.SAML1ArtifactEncoder"\r
+\r
+ /** MessageEncoder for SAML 1.x Browser/POST "binding" (really part of profile) */\r
+ #define SAML1_POST_ENCODER "org.opensaml.saml1.binding.SAML1POSTEncoder"\r
+};\r
+\r
+#endif /* __saml_encoder_h__ */\r
--- /dev/null
+/*
+ * Copyright 2001-2006 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * ArtifactMap.cpp
+ *
+ * Helper class for SAMLArtifact mapping and retrieval.
+ */
+
+#include "internal.h"
+#include "exceptions.h"
+#include "binding/ArtifactMap.h"
+#include "binding/SAMLArtifact.h"
+
+#include <log4cpp/Category.hh>
+#include <xercesc/util/XMLUniDefs.hpp>
+#include <xmltooling/XMLObjectBuilder.h>
+#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/XMLHelper.h>
+
+using namespace opensaml;
+using namespace xmltooling;
+using namespace log4cpp;
+using namespace std;
+
+namespace opensaml {
+ // In-memory storage of mappings instead of using storage API.
+ class SAML_DLLLOCAL ArtifactMappings
+ {
+ public:
+ ArtifactMappings() : m_lock(Mutex::create()) {}
+ ~ArtifactMappings() {
+ delete m_lock;
+ for (map<string,Mapping>::iterator i=m_artMap.begin(); i!=m_artMap.end(); ++i)
+ delete i->second.m_xml;
+ }
+ void storeContent(XMLObject* content, const SAMLArtifact* artifact, const char* relyingParty, int TTL);
+ XMLObject* retrieveContent(const SAMLArtifact* artifact, const char* relyingParty);
+
+ private:
+ struct SAML_DLLLOCAL Mapping {
+ Mapping() : m_xml(NULL), m_expires(0) {}
+ XMLObject* m_xml;
+ string m_relying;
+ time_t m_expires;
+ };
+
+ void removeMapping(const map<string,Mapping>::iterator& i);
+
+ Mutex* m_lock;
+ map<string,Mapping> m_artMap;
+ multimap<time_t,string> m_expMap;
+ };
+};
+
+void ArtifactMappings::removeMapping(const map<string,Mapping>::iterator& i)
+{
+ // Update secondary map.
+ pair<multimap<time_t,string>::iterator,multimap<time_t,string>::iterator> range =
+ m_expMap.equal_range(i->second.m_expires);
+ for (; range.first != range.second; ++range.first) {
+ if (range.first->second == i->first) {
+ m_expMap.erase(range.first);
+ break;
+ }
+ }
+ delete i->second.m_xml;
+ m_artMap.erase(i);
+}
+
+void ArtifactMappings::storeContent(XMLObject* content, const SAMLArtifact* artifact, const char* relyingParty, int TTL)
+{
+ Lock wrapper(m_lock);
+
+ // Garbage collect any expired artifacts.
+ time_t now=time(NULL);
+ multimap<time_t,string>::iterator stop=m_expMap.upper_bound(now);
+ for (multimap<time_t,string>::iterator i=m_expMap.begin(); i!=stop; m_expMap.erase(i++)) {
+ delete m_artMap[i->second].m_xml;
+ m_artMap.erase(i->second);
+ }
+
+ // Key is the hexed handle.
+ string hexed = SAMLArtifact::toHex(artifact->getMessageHandle());
+ Mapping& m = m_artMap[hexed];
+ m.m_xml = content;
+ if (relyingParty)
+ m.m_relying = relyingParty;
+ m.m_expires = now + TTL;
+ m_expMap.insert(make_pair(m.m_expires,hexed));
+}
+
+XMLObject* ArtifactMappings::retrieveContent(const SAMLArtifact* artifact, const char* relyingParty)
+{
+ Category& log=Category::getInstance(SAML_LOGCAT".ArtifactMap");
+ Lock wrapper(m_lock);
+
+ map<string,Mapping>::iterator i=m_artMap.find(SAMLArtifact::toHex(artifact->getMessageHandle()));
+ if (i==m_artMap.end())
+ throw BindingException("Requested artifact not in map or may have expired.");
+
+ if (!(i->second.m_relying.empty())) {
+ if (!relyingParty || i->second.m_relying != relyingParty) {
+ log.warn(
+ "request from (%s) for artifact issued to (%s)",
+ relyingParty ? relyingParty : "unknown", i->second.m_relying.c_str()
+ );
+ removeMapping(i);
+ throw BindingException("Unauthorized artifact mapping request.");
+ }
+ }
+
+ if (time(NULL) >= i->second.m_expires) {
+ removeMapping(i);
+ throw BindingException("Requested artifact has expired.");
+ }
+
+ log.debug("resolved artifact for (%s)", relyingParty ? relyingParty : "unknown");
+ XMLObject* ret = i->second.m_xml;
+ i->second.m_xml = NULL; // clear member so it doesn't get deleted
+ removeMapping(i);
+ return ret;
+}
+
+ArtifactMap::ArtifactMap(xmltooling::StorageService* storage, const char* context, int artifactTTL)
+ : m_storage(storage), m_context(context ? context : "opensaml::ArtifactMap"), m_mappings(NULL), m_artifactTTL(artifactTTL)
+{
+ if (!m_storage)
+ m_mappings = new ArtifactMappings();
+}
+
+ArtifactMap::~ArtifactMap()
+{
+ delete m_mappings;
+}
+
+static const XMLCh M[] = UNICODE_LITERAL_7(M,a,p,p,i,n,g);
+static const XMLCh RP[] = UNICODE_LITERAL_12(r,e,l,y,i,n,g,P,a,r,t,y);
+
+void ArtifactMap::storeContent(XMLObject* content, const SAMLArtifact* artifact, const char* relyingParty)
+{
+ if (content->getParent())
+ throw BindingException("Cannot store artifact mapping for XML content with parent.");
+ else if (!m_storage)
+ return m_mappings->storeContent(content, artifact, relyingParty, m_artifactTTL);
+
+ // Marshall with defaulted document, to reuse existing DOM and/or create a bound Document.
+ DOMElement* root = content->marshall();
+
+ // Build a DOM with the same document to store the relyingParty mapping.
+ if (relyingParty) {
+ auto_ptr_XMLCh temp(relyingParty);
+ root = root->getOwnerDocument()->createElementNS(NULL,M);
+ root->setAttributeNS(NULL,RP,temp.get());
+ root->appendChild(content->getDOM());
+ }
+
+ // Serialize the root element, whatever it is, for storage.
+ string xmlbuf;
+ XMLHelper::serialize(root, xmlbuf);
+ m_storage->createText(
+ m_context.c_str(), SAMLArtifact::toHex(artifact->getMessageHandle()).c_str(), xmlbuf.c_str(), time(NULL) + m_artifactTTL
+ );
+
+ // Cleanup by destroying XML.
+ delete content;
+}
+
+XMLObject* ArtifactMap::retrieveContent(const SAMLArtifact* artifact, const char* relyingParty)
+{
+#ifdef _DEBUG
+ xmltooling::NDC ndc("retrieveContent");
+#endif
+
+ if (!m_storage)
+ return m_mappings->retrieveContent(artifact, relyingParty);
+
+ string xmlbuf;
+ string key = SAMLArtifact::toHex(artifact->getMessageHandle());
+ if (!m_storage->readText(m_context.c_str(), key.c_str(), &xmlbuf))
+ throw BindingException("Artifact not found in mapping database.");
+
+ istringstream is(xmlbuf);
+ DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(is);
+ XercesJanitor<DOMDocument> janitor(doc);
+
+ Category& log=Category::getInstance(SAML_LOGCAT".ArtifactMap");
+ m_storage->deleteText(m_context.c_str(), key.c_str());
+
+ // Check the root element.
+ DOMElement* messageRoot = doc->getDocumentElement();
+ if (XMLHelper::isNodeNamed(messageRoot, NULL, M)) {
+ auto_ptr_char temp(messageRoot->getAttributeNS(NULL,RP));
+ if (!relyingParty || strcmp(temp.get(),relyingParty)) {
+ log.warn("request from (%s) for artifact issued to (%s)", relyingParty ? relyingParty : "unknown", temp.get());
+ throw BindingException("Unauthorized artifact mapping request.");
+ }
+ messageRoot = XMLHelper::getFirstChildElement(messageRoot);
+ }
+
+ // Unmarshall...
+ XMLObject* xmlObject = XMLObjectBuilder::buildOneFromElement(messageRoot, true); // bind document
+ janitor.release();
+
+ log.debug("resolved artifact for (%s)", relyingParty ? relyingParty : "unknown");
+ return xmlObject;
+}
--- /dev/null
+/*
+ * Copyright 2001-2006 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * MessageEncoder.cpp
+ *
+ * Interface to SAML protocol binding message encoders.
+ */
+
+#include "internal.h"
+#include "binding/MessageEncoder.h"
+
+using namespace opensaml;
+using namespace xmltooling;
+using namespace std;
+
+namespace opensaml {
+ namespace saml1p {
+ SAML_DLLLOCAL PluginManager<MessageEncoder,const DOMElement*>::Factory SAML1ArtifactEncoderFactory;
+ SAML_DLLLOCAL PluginManager<MessageEncoder,const DOMElement*>::Factory SAML1POSTEncoderFactory;
+ };
+};
+
+void SAML_API opensaml::registerMessageEncoders()
+{
+ SAMLConfig& conf=SAMLConfig::getConfig();
+ conf.MessageEncoderManager.registerFactory(SAML1_ARTIFACT_ENCODER, saml1p::SAML1ArtifactEncoderFactory);
+ conf.MessageEncoderManager.registerFactory(SAML1_POST_ENCODER, saml1p::SAML1POSTEncoderFactory);
+}
#include <xmltooling/exceptions.h>
namespace opensaml {
-
+ DECL_XMLTOOLING_EXCEPTION(BindingException,SAML_EXCEPTIONAPI(SAML_API),opensaml,xmltooling::XMLToolingException,Exceptions in SAML binding processing);
};
#endif /* __saml_exceptions_h__ */
Name="impl"\r
>\r
<File\r
+ RelativePath=".\saml1\binding\impl\SAML1ArtifactEncoder.cpp"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\saml1\binding\impl\SAML1POSTEncoder.cpp"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath=".\saml1\binding\impl\SAMLArtifactType0001.cpp"\r
>\r
</File>\r
Name="impl"\r
>\r
<File\r
+ RelativePath=".\binding\impl\ArtifactMap.cpp"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\binding\impl\MessageEncoder.cpp"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath=".\binding\impl\SAMLArtifact.cpp"\r
>\r
</File>\r
Name="binding"\r
>\r
<File\r
+ RelativePath=".\saml1\binding\SAML1ArtifactEncoder.h"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\saml1\binding\SAML1POSTEncoder.h"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath=".\saml1\binding\SAMLArtifactType0001.h"\r
>\r
</File>\r
Name="binding"\r
>\r
<File\r
+ RelativePath=".\binding\ArtifactMap.h"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\binding\MessageEncoder.h"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath=".\binding\SAMLArtifact.h"\r
>\r
</File>\r
--- /dev/null
+/*
+ * Copyright 2001-2006 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file saml/saml1/binding/SAML1ArtifactEncoder.h
+ *
+ * SAML 1.x Artifact binding/profile message encoder
+ */
+
+#include <saml/binding/MessageEncoder.h>
+
+
+namespace opensaml {
+ namespace saml1p {
+
+ /**
+ * SAML 1.x Artifact binding/profile message encoder
+ */
+ class SAML_API SAML1ArtifactEncoder : public MessageEncoder
+ {
+ public:
+ SAML1ArtifactEncoder(const DOMElement* e);
+ virtual ~SAML1ArtifactEncoder();
+
+ void encode(
+ std::map<std::string,std::string>& outputFields,
+ xmltooling::XMLObject* xmlObject,
+ const char* recipientID=NULL,
+ const char* relayState=NULL,
+ const xmlsignature::CredentialResolver* credResolver=NULL,
+ const XMLCh* sigAlgorithm=NULL
+ ) const;
+ };
+
+ };
+};
--- /dev/null
+/*
+ * Copyright 2001-2006 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file saml/saml1/binding/SAML1POSTEncoder.h
+ *
+ * SAML 1.x POST binding/profile message encoder
+ */
+
+#include <saml/binding/MessageEncoder.h>
+
+
+namespace opensaml {
+ namespace saml1p {
+
+ /**
+ * SAML 1.x POST binding/profile message encoder
+ */
+ class SAML_API SAML1POSTEncoder : public MessageEncoder
+ {
+ public:
+ SAML1POSTEncoder(const DOMElement* e);
+ virtual ~SAML1POSTEncoder();
+
+ void encode(
+ std::map<std::string,std::string>& outputFields,
+ xmltooling::XMLObject* xmlObject,
+ const char* recipientID=NULL,
+ const char* relayState=NULL,
+ const xmlsignature::CredentialResolver* credResolver=NULL,
+ const XMLCh* sigAlgorithm=NULL
+ ) const;
+ };
+
+ };
+};
--- /dev/null
+/*
+ * Copyright 2001-2006 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * SAML1ArtifactEncoder.cpp
+ *
+ * SAML 1.x Artifact binding/profile message encoder
+ */
+
+#include "internal.h"
+#include "exceptions.h"
+#include "saml/binding/SAMLArtifact.h"
+#include "saml1/binding/SAML1ArtifactEncoder.h"
+#include "saml1/core/Assertions.h"
+
+#include <log4cpp/Category.hh>
+#include <xmltooling/util/NDC.h>
+
+using namespace opensaml::saml1;
+using namespace opensaml::saml1p;
+using namespace opensaml;
+using namespace xmlsignature;
+using namespace xmltooling;
+using namespace log4cpp;
+using namespace std;
+
+namespace opensaml {
+ namespace saml1p {
+ MessageEncoder* SAML_DLLLOCAL SAML1ArtifactEncoderFactory(const DOMElement* const & e)
+ {
+ return new SAML1ArtifactEncoder(e);
+ }
+ };
+};
+
+SAML1ArtifactEncoder::SAML1ArtifactEncoder(const DOMElement* e) {}
+
+SAML1ArtifactEncoder::~SAML1ArtifactEncoder() {}
+
+void SAML1ArtifactEncoder::encode(
+ map<string,string>& outputFields,
+ XMLObject* xmlObject,
+ const char* recipientID,
+ const char* relayState,
+ const CredentialResolver* credResolver,
+ const XMLCh* sigAlgorithm
+ ) const
+{
+#ifdef _DEBUG
+ xmltooling::NDC ndc("encode");
+#endif
+ Category& log = Category::getInstance(SAML_LOGCAT".MessageEncoder.SAML1Artifact");
+ log.debug("validating input");
+
+ outputFields.clear();
+ if (xmlObject->getParent())
+ throw BindingException("Cannot encode XML content with parent.");
+ Assertion* assertion = dynamic_cast<Assertion*>(xmlObject);
+ if (!assertion)
+ throw BindingException("XML content for SAML 1.x Artifact Encoder must be a SAML 1.x <Assertion>.");
+ if (!relayState)
+ throw BindingException("SAML 1.x Artifact Encoder requires relay state (TARGET) value.");
+
+ // Signing is a protocol level issue, so no signing here...
+
+ ArtifactMap* mapper = SAMLConfig::getConfig().getArtifactMap();
+ if (!mapper)
+ throw BindingException("SAML 1.x Artifact Encoder requires ArtifactMap be set in configuration.");
+
+ // Obtain a fresh artifact.
+ if (!m_artifactGenerator)
+ throw BindingException("SAML 1.x Artifact Encoder requires an ArtifactGenerator instance.");
+ log.debug("obtaining new artifact for relying party (%s)", recipientID ? recipientID : "unknown");
+ auto_ptr<SAMLArtifact> artifact(m_artifactGenerator->generateSAML1Artifact(recipientID));
+
+ // Pass back output fields.
+ outputFields["SAMLart"] = artifact->encode();
+ outputFields["TARGET"] = relayState;
+
+ // Store the assertion. Last step in storage will be to delete the XML.
+ log.debug("storing artifact and content in map");
+ mapper->storeContent(xmlObject, artifact.get(), recipientID);
+
+ log.debug("message encoded");
+}
--- /dev/null
+/*
+ * Copyright 2001-2006 Internet2
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * SAML1POSTEncoder.cpp
+ *
+ * SAML 1.x Artifact binding/profile message encoder
+ */
+
+#include "internal.h"
+#include "exceptions.h"
+#include "saml1/binding/SAML1POSTEncoder.h"
+#include "saml1/core/Protocols.h"
+
+#include <log4cpp/Category.hh>
+#include <xercesc/util/Base64.hpp>
+#include <xmltooling/util/NDC.h>
+
+using namespace opensaml::saml1p;
+using namespace opensaml;
+using namespace xmlsignature;
+using namespace xmltooling;
+using namespace log4cpp;
+using namespace std;
+
+namespace opensaml {
+ namespace saml1p {
+ MessageEncoder* SAML_DLLLOCAL SAML1POSTEncoderFactory(const DOMElement* const & e)
+ {
+ return new SAML1POSTEncoder(e);
+ }
+
+ class SAML_DLLLOCAL _addcert : public binary_function<X509Data*,XSECCryptoX509*,void> {
+ public:
+ void operator()(X509Data* bag, XSECCryptoX509* cert) const {
+ safeBuffer& buf=cert->getDEREncodingSB();
+ X509Certificate* x=X509CertificateBuilder::buildX509Certificate();
+ x->setValue(buf.sbStrToXMLCh());
+ bag->getX509Certificates().push_back(x);
+ }
+ };
+ };
+};
+
+SAML1POSTEncoder::SAML1POSTEncoder(const DOMElement* e) {}
+
+SAML1POSTEncoder::~SAML1POSTEncoder() {}
+
+void SAML1POSTEncoder::encode(
+ map<string,string>& outputFields,
+ XMLObject* xmlObject,
+ const char* recipientID,
+ const char* relayState,
+ const CredentialResolver* credResolver,
+ const XMLCh* sigAlgorithm
+ ) const
+{
+#ifdef _DEBUG
+ xmltooling::NDC ndc("encode");
+#endif
+ Category& log = Category::getInstance(SAML_LOGCAT".MessageEncoder.SAML1POST");
+ log.debug("validating input");
+
+ outputFields.clear();
+ if (xmlObject->getParent())
+ throw BindingException("Cannot encode XML content with parent.");
+ Response* response = dynamic_cast<Response*>(xmlObject);
+ if (!response)
+ throw BindingException("XML content for SAML 1.x POST Encoder must be a SAML 1.x <Response>.");
+ if (!relayState)
+ throw BindingException("SAML 1.x POST Encoder requires relay state (TARGET) value.");
+
+ DOMElement* rootElement = NULL;
+ if (credResolver) {
+ // Signature based on native XML signing.
+ if (response->getSignature()) {
+ log.debug("response already signed, skipping signature operation");
+ }
+ else {
+ log.debug("signing and marshalling the response");
+
+ // Append a Signature.
+ response->setSignature(SignatureBuilder::buildSignature());
+ response->getSignature()->setSigningKey(credResolver->getKey());
+
+ // Build KeyInfo.
+ const vector<XSECCryptoX509*>& certs = credResolver->getCertificates();
+ if (!certs.empty()) {
+ KeyInfo* keyInfo=KeyInfoBuilder::buildKeyInfo();
+ X509Data* x509Data=X509DataBuilder::buildX509Data();
+ keyInfo->getX509Datas().push_back(x509Data);
+ for_each(certs.begin(),certs.end(),bind1st(_addcert(),x509Data));
+ response->getSignature()->setKeyInfo(keyInfo);
+ }
+
+ // Sign response while marshalling.
+ vector<Signature*> sigs(1,response->getSignature());
+ rootElement = response->marshall((DOMDocument*)NULL,&sigs);
+ }
+ }
+ else {
+ log.debug("marshalling the response");
+ rootElement = response->marshall();
+ }
+
+ string xmlbuf;
+ XMLHelper::serialize(rootElement, xmlbuf);
+ unsigned int len=0;
+ XMLByte* out=Base64::encode(reinterpret_cast<const XMLByte*>(xmlbuf.data()),xmlbuf.size(),&len);
+ if (out) {
+ xmlbuf.erase();
+ xmlbuf.append(reinterpret_cast<char*>(out),len);
+ XMLString::release(&out);
+ }
+ else {
+ throw BindingException("Base64 encoding of XML failed.");
+ }
+
+ // Pass back output fields.
+ outputFields["SAMLResponse"] = xmlbuf;
+ outputFields["TARGET"] = relayState;
+
+ // Cleanup by destroying XML.
+ delete xmlObject;
+
+ log.debug("message encoded");
+}
*/
/**
- * BlacklistMetadataFilter.cpp
+ * SignatureMetadataFilter.cpp
*
- * Removes blacklisted entities from a metadata instance
+ * Filters out unsigned or mis-signed elements.
*/
#include "internal.h"
--- /dev/null
+/*\r
+ * Copyright 2001-2005 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+#include "internal.h"\r
+#include <saml/SAMLConfig.h>\r
+#include <saml/saml2/binding/SAML2ArtifactType0004.h>\r
+#include <saml/saml2/core/Protocols.h>\r
+\r
+using namespace opensaml::saml2p;\r
+using namespace opensaml;\r
+using namespace std;\r
+\r
+class ArtifactMapTest : public CxxTest::TestSuite\r
+{\r
+public:\r
+ string providerIdStr;\r
+ string handle;\r
+ ArtifactMap* artifactMap;\r
+ void setUp() {\r
+ if (handle.empty()) {\r
+ providerIdStr = "https://idp.org/SAML";\r
+ SAMLConfig::getConfig().generateRandomBytes(handle,SAML2ArtifactType0004::HANDLE_LENGTH);\r
+ }\r
+ artifactMap = new ArtifactMap();\r
+ }\r
+ void tearDown() {\r
+ delete artifactMap;\r
+ artifactMap=NULL;\r
+ }\r
+ void testArtifactMap(void) {\r
+ auto_ptr<Response> response(ResponseBuilder::buildResponse());\r
+\r
+ SAML2ArtifactType0004 artifact(SAMLConfig::getConfig().hashSHA1(providerIdStr.c_str()),666,handle);\r
+\r
+ artifactMap->storeContent(response.get(), &artifact, providerIdStr.c_str());\r
+ response.release();\r
+\r
+ auto_ptr<XMLObject> xmlObject(artifactMap->retrieveContent(&artifact, providerIdStr.c_str()));\r
+ TSM_ASSERT_THROWS("Artifact resolution improperly succeeded.", artifactMap->retrieveContent(&artifact), BindingException);\r
+ TSM_ASSERT("Mapped content was not a Response.", dynamic_cast<Response*>(xmlObject.get())!=NULL);\r
+ }\r
+};\r
SAMLArtifactType0001Test.h \
SAMLArtifactType0002Test.h \
SAMLArtifactType0004Test.h \
+ ArtifactMapTest.h \
signature/SAML1AssertionTest.h \
signature/SAML1RequestTest.h \
signature/SAML1ResponseTest.h \
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"\r
>\r
<File\r
+ RelativePath=".\ArtifactMapTest.cpp"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath=".\SAMLArtifactCreationTest.cpp"\r
>\r
</File>\r
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"\r
>\r
<File\r
+ RelativePath=".\ArtifactMapTest.h"\r
+ >\r
+ <FileConfiguration\r
+ Name="Debug|Win32"\r
+ >\r
+ <Tool\r
+ Name="VCCustomBuildTool"\r
+ CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o "$(InputDir)$(InputName)".cpp "$(InputPath)""\r
+ Outputs=""$(InputDir)$(InputName)".cpp"\r
+ />\r
+ </FileConfiguration>\r
+ <FileConfiguration\r
+ Name="Release|Win32"\r
+ >\r
+ <Tool\r
+ Name="VCCustomBuildTool"\r
+ CommandLine="\perl\bin\perl.exe -w \cxxtest\cxxtestgen.pl --part --have-eh --have-std --abort-on-fail -o "$(InputDir)$(InputName)".cpp "$(InputPath)""\r
+ Outputs=""$(InputDir)$(InputName)".cpp"\r
+ />\r
+ </FileConfiguration>\r
+ </File>\r
+ <File\r
RelativePath=".\internal.h"\r
>\r
</File>\r