/**
* Interface to caller-supplied shim for accessing HTTP request context.
*
- * To supply information from the surrounding web server environment,
+ * <p>To supply information from the surrounding web server environment,
* a shim must be supplied in the form of this interface to adapt the
* library to different proprietary server APIs.
+ *
+ * <p>This interface need not be threadsafe.
*/
class SAML_API HTTPRequest {
MAKE_NONCOPYABLE(HTTPRequest);
* @return the query string
*/
virtual const char* getQueryString() const=0;
+
+ /**
+ * Returns the raw HTTP request body. Used to access the body
+ * of a POST that is not in URL-encoded form.
+ *
+ * @return the request body, or NULL
+ */
+ virtual const char* getRequestBody() const=0;
/**
* Returns a decoded named parameter value from the query string or form body.
virtual std::vector<const char*>::size_type getParameters(
const char* name, std::vector<const char*>& values
) const=0;
+
+ /**
+ * Returns the authenticated identity associated with the request
+ *
+ * @return the authenticated username or an empty string
+ */
+ virtual std::string getRemoteUser() const=0;
+
+ /**
+ * Returns a request header value.
+ *
+ * @param name the name of the header to return
+ * @return the header's value, or an empty string
+ */
+ virtual std::string getHeader(const char* name) const=0;
};
/**
#include <map>
#include <string>
+#include <istream>
#include <xmltooling/XMLObject.h>
#include <xmltooling/signature/CredentialResolver.h>
virtual ~MessageEncoder() {}
/**
+ * Interface to caller-supplied shim for issuing an HTTP response.
+ *
+ * <p>To supply information to the surrounding web server environment,
+ * a shim must be supplied in the form of this interface to adapt the
+ * library to different proprietary server APIs.
+ *
+ * <p>This interface need not be threadsafe.
+ */
+ class SAML_API HTTPResponse {
+ MAKE_NONCOPYABLE(HTTPResponse);
+ protected:
+ HTTPResponse() {}
+ public:
+ virtual ~HTTPResponse() {}
+
+ /**
+ * Sets or clears a response header.
+ *
+ * @param name header name
+ * @param value value to set, or NULL to clear
+ */
+ virtual void setHeader(const char* name, const char* value)=0;
+
+ /**
+ * Sets a client cookie.
+ *
+ * @param name cookie name
+ * @param value value to set, or NULL to clear
+ */
+ virtual void setCookie(const char* name, const char* value)=0;
+
+ /**
+ * Redirect the client to the specified URL and complete the response.
+ * Any headers previously set will be sent ahead of the redirect.
+ *
+ * @param url location to redirect client
+ * @return a result code to return from the calling MessageEncoder
+ */
+ virtual long sendRedirect(const char* url)=0;
+
+ /**
+ * Sends a completed response to the client. Any headers previously set
+ * will be sent ahead of the data.
+ *
+ * @param inputStream reference to source of response data
+ * @param status HTTP status code to return
+ * @param contentType Content-Type header to return
+ * @return a result code to return from the calling MessageEncoder
+ */
+ virtual long sendResponse(std::istream& inputStream, int status = 200, const char* contentType = "text/html")=0;
+ };
+
+ /**
* Interface to caller-supplied artifact generation mechanism.
*
* Generating an artifact for storage and retrieval requires knowledge of
}
/**
- * Encodes an XML object/message into a set of binding-specific data "fields".
+ * Encodes an XML object/message into a binding-specific HTTP response.
* The XML content cannot have a parent object, and any existing references to
* the content will be invalidated if the encode method returns successfully.
*
* binding-specific manner. The CredentialResolver <strong>MUST</strong>
* be locked by the caller.
*
- * <p>An embedded URLEncoder instance may be required by some bindings
- * in order to produce predictable signature input.
- *
* <p>Artifact-based bindings require an ArtifactGenerator be set to
* produce an artifact suitable for the intended recipient.
*
- * <p>Note that the name/value pairs resulting from the encoding operation are
- * <strong>NOT</strong> URL-encoded or otherwise transformed. It is the caller's
- * responsibility to apply any necessary encoding when preparing the data for
- * transport.
- *
- * @param outputFields name/value pairs containing the results of encoding the message
- * @param xmlObject XML object/message to encode
+ * @param httpResponse reference to interface for sending encoded response to client
+ * @param xmlObject XML message to encode
+ * @param destination destination URL for message
* @param recipientID optional entityID of message recipient
* @param relayState optional RelayState value to accompany message
* @param credResolver optional CredentialResolver instance to supply signing material
* @param sigAlgorithm optional signature algorithm identifier
*/
- virtual void encode(
- std::map<std::string,std::string>& outputFields,
+ virtual long encode(
+ HTTPResponse& httpResponse,
xmltooling::XMLObject* xmlObject,
+ const char* destination,
const char* recipientID=NULL,
const char* relayState=NULL,
const xmlsignature::CredentialResolver* credResolver=NULL,
SAML1ArtifactEncoder(const DOMElement* e);
virtual ~SAML1ArtifactEncoder();
- void encode(
- std::map<std::string,std::string>& outputFields,
+ long encode(
+ HTTPResponse& httpResponse,
xmltooling::XMLObject* xmlObject,
+ const char* destination,
const char* recipientID=NULL,
const char* relayState=NULL,
const xmlsignature::CredentialResolver* credResolver=NULL,
SAML1POSTEncoder(const DOMElement* e);
virtual ~SAML1POSTEncoder();
- void encode(
- std::map<std::string,std::string>& outputFields,
+ long encode(
+ HTTPResponse& httpResponse,
xmltooling::XMLObject* xmlObject,
+ const char* destination,
const char* recipientID=NULL,
const char* relayState=NULL,
const xmlsignature::CredentialResolver* credResolver=NULL,
const XMLCh* sigAlgorithm=NULL
) const;
- };
+
+ protected:
+ /** Pathname of HTML template for transmission of message via POST. */
+ std::string m_template;
+ };
};
};
#include "internal.h"
#include "exceptions.h"
-#include "saml/binding/ArtifactMap.h"
-#include "saml/binding/SAMLArtifact.h"
+#include "binding/ArtifactMap.h"
+#include "binding/SAMLArtifact.h"
+#include "binding/URLEncoder.h"
#include "saml1/binding/SAML1ArtifactEncoder.h"
#include "saml1/core/Assertions.h"
SAML1ArtifactEncoder::~SAML1ArtifactEncoder() {}
-void SAML1ArtifactEncoder::encode(
- map<string,string>& outputFields,
+long SAML1ArtifactEncoder::encode(
+ HTTPResponse& httpResponse,
XMLObject* xmlObject,
+ const char* destination,
const char* recipientID,
const char* relayState,
const CredentialResolver* credResolver,
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);
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");
+ // Generate redirect.
+ string loc = destination;
+ loc += (strchr(destination,'?') ? '&' : '?');
+ URLEncoder* escaper = SAMLConfig::getConfig().getURLEncoder();
+ loc = loc + "SAMLart=" + escaper->encode(artifact->encode().c_str()) + "&TARGET=" + escaper->encode(relayState);
+ log.debug("message encoded, sending redirect to client");
+ return httpResponse.sendRedirect(loc.c_str());
}
#include "saml1/binding/SAML1POSTEncoder.h"
#include "saml1/core/Protocols.h"
+#include <fstream>
+#include <sstream>
#include <log4cpp/Category.hh>
#include <xercesc/util/Base64.hpp>
#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/TemplateEngine.h>
using namespace opensaml::saml1p;
using namespace opensaml;
};
};
-SAML1POSTEncoder::SAML1POSTEncoder(const DOMElement* e) {}
+static const XMLCh templat[] = UNICODE_LITERAL_8(t,e,m,p,l,a,t,e);
+
+SAML1POSTEncoder::SAML1POSTEncoder(const DOMElement* e)
+{
+ if (e) {
+ auto_ptr_char t(e->getAttributeNS(NULL, templat));
+ if (t.get())
+ m_template = t.get();
+ }
+ if (m_template.empty())
+ throw XMLToolingException("SAML1POSTEncoder requires template attribute.");
+}
SAML1POSTEncoder::~SAML1POSTEncoder() {}
-void SAML1POSTEncoder::encode(
- map<string,string>& outputFields,
+long SAML1POSTEncoder::encode(
+ HTTPResponse& httpResponse,
XMLObject* xmlObject,
+ const char* destination,
const char* recipientID,
const char* relayState,
const CredentialResolver* credResolver,
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);
else {
throw BindingException("Base64 encoding of XML failed.");
}
-
- // Pass back output fields.
- outputFields["SAMLResponse"] = xmlbuf;
- outputFields["TARGET"] = relayState;
+
+ // Push message into template and send result to client.
+ log.debug("message encoded, sending HTML form template to client");
+ TemplateEngine* engine = XMLToolingConfig::getConfig().getTemplateEngine();
+ if (!engine)
+ throw BindingException("Encoding response using POST requires a TemplateEngine instance.");
+ ifstream infile(m_template.c_str());
+ if (!infile)
+ throw BindingException("Failed to open HTML template for POST response ($1).", params(1,m_template.c_str()));
+ map<string,string> params;
+ params["action"] = destination;
+ params["SAMLResponse"] = xmlbuf;
+ params["TARGET"] = relayState;
+ stringstream s;
+ engine->run(infile, s, params);
+ long ret = httpResponse.sendResponse(s);
// Cleanup by destroying XML.
delete xmlObject;
-
- log.debug("message encoded");
+ return ret;
}
SAML2ArtifactEncoder(const DOMElement* e);
virtual ~SAML2ArtifactEncoder();
- void encode(
- std::map<std::string,std::string>& outputFields,
+ long encode(
+ HTTPResponse& httpResponse,
xmltooling::XMLObject* xmlObject,
+ const char* destination,
const char* recipientID=NULL,
const char* relayState=NULL,
const xmlsignature::CredentialResolver* credResolver=NULL,
const XMLCh* sigAlgorithm=NULL
) const;
- };
+
+ protected:
+ /** Pathname of HTML template for transmission of message via POST. */
+ std::string m_template;
+ };
};
};
SAML2POSTEncoder(const DOMElement* e);
virtual ~SAML2POSTEncoder();
- void encode(
- std::map<std::string,std::string>& outputFields,
+ long encode(
+ HTTPResponse& httpResponse,
xmltooling::XMLObject* xmlObject,
+ const char* destination,
const char* recipientID=NULL,
const char* relayState=NULL,
const xmlsignature::CredentialResolver* credResolver=NULL,
const XMLCh* sigAlgorithm=NULL
) const;
- };
+
+ protected:
+ /** Pathname of HTML template for transmission of message via POST. */
+ std::string m_template;
+ };
};
};
#include "internal.h"
#include "exceptions.h"
-#include "saml/binding/ArtifactMap.h"
+#include "binding/ArtifactMap.h"
+#include "binding/URLEncoder.h"
#include "saml2/binding/SAML2Artifact.h"
#include "saml2/binding/SAML2ArtifactEncoder.h"
#include "saml2/core/Protocols.h"
+#include <fstream>
+#include <sstream>
#include <log4cpp/Category.hh>
#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/TemplateEngine.h>
using namespace opensaml::saml2p;
using namespace opensaml;
};
};
-SAML2ArtifactEncoder::SAML2ArtifactEncoder(const DOMElement* e) {}
+static const XMLCh templat[] = UNICODE_LITERAL_8(t,e,m,p,l,a,t,e);
+
+SAML2ArtifactEncoder::SAML2ArtifactEncoder(const DOMElement* e)
+{
+ if (e) {
+ auto_ptr_char t(e->getAttributeNS(NULL, templat));
+ if (t.get())
+ m_template = t.get();
+ }
+}
SAML2ArtifactEncoder::~SAML2ArtifactEncoder() {}
-void SAML2ArtifactEncoder::encode(
- map<string,string>& outputFields,
- XMLObject* xmlObject,
+long SAML2ArtifactEncoder::encode(
+ HTTPResponse& httpResponse,
+ xmltooling::XMLObject* xmlObject,
+ const char* destination,
const char* recipientID,
const char* relayState,
const CredentialResolver* credResolver,
Category& log = Category::getInstance(SAML_LOGCAT".MessageEncoder.SAML2Artifact");
log.debug("validating input");
- outputFields.clear();
+ if (relayState && strlen(relayState)>80)
+ throw BindingException("RelayState cannot exceed 80 bytes in length.");
+
if (xmlObject->getParent())
throw BindingException("Cannot encode XML content with parent.");
}
}
- // Pass back output fields.
- outputFields["SAMLart"] = artifact->encode();
- if (relayState)
- outputFields["RelayState"] = relayState;
-
// Store the message. 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");
+ if (m_template.empty()) {
+ // Generate redirect.
+ string loc = destination;
+ loc += (strchr(destination,'?') ? '&' : '?');
+ URLEncoder* escaper = SAMLConfig::getConfig().getURLEncoder();
+ loc = loc + "SAMLart=" + escaper->encode(artifact->encode().c_str());
+ if (relayState)
+ loc = loc + "&RelayState=" + escaper->encode(relayState);
+ log.debug("message encoded, sending redirect to client");
+ return httpResponse.sendRedirect(loc.c_str());
+ }
+ else {
+ // Push message into template and send result to client.
+ log.debug("message encoded, sending HTML form template to client");
+ TemplateEngine* engine = XMLToolingConfig::getConfig().getTemplateEngine();
+ if (!engine)
+ throw BindingException("Encoding artifact using POST requires a TemplateEngine instance.");
+ ifstream infile(m_template.c_str());
+ if (!infile)
+ throw BindingException("Failed to open HTML template for POST response ($1).", params(1,m_template.c_str()));
+ map<string,string> params;
+ params["action"] = destination;
+ params["SAMLart"] = artifact->encode();
+ if (relayState)
+ params["RelayState"] = relayState;
+ stringstream s;
+ engine->run(infile, s, params);
+ return httpResponse.sendResponse(s);
+ }
}
#include "saml2/binding/SAML2POSTEncoder.h"
#include "saml2/core/Protocols.h"
+#include <fstream>
+#include <sstream>
#include <log4cpp/Category.hh>
#include <xercesc/util/Base64.hpp>
#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/TemplateEngine.h>
using namespace opensaml::saml2p;
using namespace opensaml;
};
};
-SAML2POSTEncoder::SAML2POSTEncoder(const DOMElement* e) {}
+static const XMLCh templat[] = UNICODE_LITERAL_8(t,e,m,p,l,a,t,e);
+
+SAML2POSTEncoder::SAML2POSTEncoder(const DOMElement* e)
+{
+ if (e) {
+ auto_ptr_char t(e->getAttributeNS(NULL, templat));
+ if (t.get())
+ m_template = t.get();
+ }
+ if (m_template.empty())
+ throw XMLToolingException("SAML2POSTEncoder requires template attribute.");
+}
SAML2POSTEncoder::~SAML2POSTEncoder() {}
-void SAML2POSTEncoder::encode(
- map<string,string>& outputFields,
+long SAML2POSTEncoder::encode(
+ HTTPResponse& httpResponse,
XMLObject* xmlObject,
+ const char* destination,
const char* recipientID,
const char* relayState,
const CredentialResolver* credResolver,
Category& log = Category::getInstance(SAML_LOGCAT".MessageEncoder.SAML2POST");
log.debug("validating input");
- outputFields.clear();
if (xmlObject->getParent())
throw BindingException("Cannot encode XML content with parent.");
throw BindingException("Base64 encoding of XML failed.");
}
- // Pass back output fields.
- outputFields[request ? "SAMLRequest" : "SAMLResponse"] = xmlbuf;
+ // Push message into template and send result to client.
+ log.debug("message encoded, sending HTML form template to client");
+ TemplateEngine* engine = XMLToolingConfig::getConfig().getTemplateEngine();
+ if (!engine)
+ throw BindingException("Encoding message using POST requires a TemplateEngine instance.");
+ ifstream infile(m_template.c_str());
+ if (!infile)
+ throw BindingException("Failed to open HTML template for POST message ($1).", params(1,m_template.c_str()));
+ map<string,string> params;
+ params["action"] = destination;
+ params[request ? "SAMLRequest" : "SAMLResponse"] = xmlbuf;
if (relayState)
- outputFields["RelayState"] = relayState;
+ params["RelayState"] = relayState;
+ stringstream s;
+ engine->run(infile, s, params);
+ long ret = httpResponse.sendResponse(s);
// Cleanup by destroying XML.
delete xmlObject;
-
- log.debug("message encoded");
+ return ret;
}
#include <saml/SAMLConfig.h>
#include <saml/binding/MessageDecoder.h>
#include <saml/binding/MessageEncoder.h>
+#include <saml/binding/URLEncoder.h>
#include <saml/saml2/metadata/MetadataProvider.h>
#include <saml/security/X509TrustEngine.h>
using namespace saml2md;
using namespace xmlsignature;
-class SAMLBindingBaseTestCase : public MessageDecoder::HTTPRequest
+class SAMLBindingBaseTestCase : public MessageDecoder::HTTPRequest, public MessageEncoder::HTTPResponse
{
protected:
CredentialResolver* m_creds;
MetadataProvider* m_metadata;
opensaml::X509TrustEngine* m_trust;
map<string,string> m_fields;
+ map<string,string> m_headers;
+ string m_method,m_url;
public:
void setUp() {
m_metadata=NULL;
m_trust=NULL;
m_fields.clear();
+ m_headers.clear();
+ m_method.erase();
+ m_url.erase();
try {
string config = data_path + "binding/ExampleMetadataProvider.xml";
m_metadata=NULL;
m_trust=NULL;
m_fields.clear();
+ m_headers.clear();
+ m_method.erase();
+ m_url.erase();
}
+ // HTTPRequest methods
+
+ const char* getMethod() const {
+ return m_method.c_str();
+ }
+
+ const char* getRequestURL() const {
+ return m_url.c_str();
+ }
+
+ const char* getRequestBody() const {
+ return NULL;
+ }
+
+ const char* getQueryString() const {
+ return NULL;
+ }
+
+ string getRemoteUser() const {
+ return "";
+ }
+
+ string getHeader(const char* name) const {
+ map<string,string>::const_iterator i=m_headers.find(name);
+ return i==m_headers.end() ? "" : i->second;
+ }
+
const char* getParameter(const char* name) const {
map<string,string>::const_iterator i=m_fields.find(name);
return i==m_fields.end() ? NULL : i->second.c_str();
values.push_back(i->second.c_str());
return values.size();
}
+
+ // HTTPResponse methods
+
+ void setHeader(const char* name, const char* value) {
+ m_headers[name] = value ? value : "";
+ }
+
+ void setCookie(const char* name, const char* value) {
+ m_headers["Set-Cookie"] = string(name) + "=" + (value ? value : "");
+ }
+
+ // The amount of error checking missing from this is incredible, but as long
+ // as the test data isn't unexpected or malformed, it should work.
+
+ long sendRedirect(const char* url) {
+ m_method = "GET";
+ char* dup = strdup(url);
+ char* pch = strchr(dup,'?');
+ if (pch) {
+ *pch++=0;
+ char* name=pch;
+ while (name && *name) {
+ pch=strchr(pch,'=');
+ *pch++=0;
+ char* value=pch;
+ pch=strchr(pch,'&');
+ if (pch)
+ *pch++=0;
+ SAMLConfig::getConfig().getURLEncoder()->decode(value);
+ m_fields[name] = value;
+ name = pch;
+ }
+ }
+ m_url = dup;
+ free(dup);
+ return m_fields.size();
+ }
+
+ string html_decode(const string& s) const {
+ string decoded;
+ const char* ch=s.c_str();
+ while (*ch) {
+ if (*ch=='&') {
+ if (!strncmp(ch,"<",4)) {
+ decoded+='<'; ch+=4;
+ }
+ else if (!strncmp(ch,">",4)) {
+ decoded+='>'; ch+=4;
+ }
+ else if (!strncmp(ch,""",6)) {
+ decoded+='"'; ch+=6;
+ }
+ else if (*++ch=='#') {
+ decoded+=(char)atoi(++ch);
+ ch=strchr(ch,';')+1;
+ }
+ }
+ else {
+ decoded+=*ch++;
+ }
+ }
+ return decoded;
+ }
+
+ long sendResponse(std::istream& inputStream, int status = 200, const char* contentType = "text/html") {
+ m_method="POST";
+ string page,line;
+ while (getline(inputStream,line))
+ page += line + '\n';
+
+ const char* pch=strstr(page.c_str(),"action=\"");
+ pch+=strlen("action=\"");
+ m_url = html_decode(page.substr(pch-page.c_str(),strchr(pch,'"')-pch));
+
+ while (pch=strstr(pch,"<input type=\"hidden\" name=\"")) {
+ pch+=strlen("<input type=\"hidden\" name=\"");
+ string name = page.substr(pch-page.c_str(),strchr(pch,'"')-pch);
+ pch=strstr(pch,"value=\"");
+ pch+=strlen("value=\"");
+ m_fields[name] = html_decode(page.substr(pch-page.c_str(),strchr(pch,'"')-pch));
+ }
+ return m_fields.size();
+ }
};
--- /dev/null
+<html>
+ <head>
+ <title>SAML Binding</title>
+ </head>
+ <body>
+ <form method="POST" action="<mlp action/>">
+ <mlpif TARGET>
+ <input type="hidden" name="TARGET" value="<mlp TARGET/>"/>
+ </mlpif>
+ <mlpif RelayState>
+ <input type="hidden" name="RelayState" value="<mlp RelayState/>"/>
+ </mlpif>
+ <mlpif SAMLRequest>
+ <input type="hidden" name="SAMLRequest" value="<mlp SAMLRequest/>"/>
+ </mlpif>
+ <mlpif SAMLResponse>
+ <input type="hidden" name="SAMLResponse" value="<mlp SAMLResponse/>"/>
+ </mlpif>
+ </form>
+ </body>
+</html>
public SAMLBindingBaseTestCase, public MessageEncoder::ArtifactGenerator, public MessageDecoder::ArtifactResolver {
public:
void setUp() {
- m_fields.clear();
SAMLBindingBaseTestCase::setUp();
}
void tearDown() {
- m_fields.clear();
SAMLBindingBaseTestCase::tearDown();
}
SAMLConfig::getConfig().MessageEncoderManager.newPlugin(SAMLConstants::SAML1_PROFILE_BROWSER_ARTIFACT, NULL)
);
encoder->setArtifactGenerator(this);
- encoder->encode(m_fields,toSend.get(),"https://sp.example.org/","state",m_creds);
+ encoder->encode(*this,toSend.get(),"https://sp.example.org/SAML/Artifact","https://sp.example.org/","state",m_creds);
toSend.release();
// Decode message.
}
}
- const char* getMethod() const {
- return "GET";
- }
-
- const char* getRequestURL() const {
- return "https://sp.example.org/SAML/Artifact";
- }
-
- const char* getQueryString() const {
- return NULL;
- }
-
SAMLArtifact* generateSAML1Artifact(const char* relyingParty) const {
return new SAMLArtifactType0001(SAMLConfig::getConfig().hashSHA1("https://idp.example.org/"));
}
class SAML1POSTTest : public CxxTest::TestSuite, public SAMLBindingBaseTestCase {
public:
void setUp() {
- m_fields.clear();
SAMLBindingBaseTestCase::setUp();
}
void tearDown() {
- m_fields.clear();
SAMLBindingBaseTestCase::tearDown();
}
toSend->setIssueInstant(time(NULL));
// Encode message.
+ auto_ptr_XMLCh lit1("MessageEncoder");
+ auto_ptr_XMLCh lit2("template");
+ path = data_path + "binding/template.html";
+ auto_ptr_XMLCh lit3(path.c_str());
+ DOMDocument* encoder_config = XMLToolingConfig::getConfig().getParser().newDocument();
+ XercesJanitor<DOMDocument> janitor2(encoder_config);
+ encoder_config->appendChild(encoder_config->createElementNS(NULL,lit1.get()));
+ encoder_config->getDocumentElement()->setAttributeNS(NULL,lit2.get(),lit3.get());
auto_ptr<MessageEncoder> encoder(
- SAMLConfig::getConfig().MessageEncoderManager.newPlugin(SAMLConstants::SAML1_PROFILE_BROWSER_POST, NULL)
+ SAMLConfig::getConfig().MessageEncoderManager.newPlugin(
+ SAMLConstants::SAML1_PROFILE_BROWSER_POST, encoder_config->getDocumentElement()
+ )
);
- encoder->encode(m_fields,toSend.get(),"https://sp.example.org/","state",m_creds);
+ encoder->encode(*this,toSend.get(),"https://sp.example.org/SAML/POST","https://sp.example.org/","state",m_creds);
toSend.release();
// Decode message.
toSend->setResponseID(NULL);
// Encode message.
+ auto_ptr_XMLCh lit1("MessageEncoder");
+ auto_ptr_XMLCh lit2("template");
+ path = data_path + "binding/template.html";
+ auto_ptr_XMLCh lit3(path.c_str());
+ DOMDocument* encoder_config = XMLToolingConfig::getConfig().getParser().newDocument();
+ XercesJanitor<DOMDocument> janitor2(encoder_config);
+ encoder_config->appendChild(encoder_config->createElementNS(NULL,lit1.get()));
+ encoder_config->getDocumentElement()->setAttributeNS(NULL,lit2.get(),lit3.get());
auto_ptr<MessageEncoder> encoder(
- SAMLConfig::getConfig().MessageEncoderManager.newPlugin(SAMLConstants::SAML1_PROFILE_BROWSER_POST, NULL)
+ SAMLConfig::getConfig().MessageEncoderManager.newPlugin(
+ SAMLConstants::SAML1_PROFILE_BROWSER_POST, encoder_config->getDocumentElement()
+ )
);
- encoder->encode(m_fields,toSend.get(),"https://sp.example.org/","state");
+ encoder->encode(*this,toSend.get(),"https://sp.example.org/SAML/POST","https://sp.example.org/","state");
toSend.release();
// Decode message.
throw;
}
}
-
- const char* getMethod() const {
- return "POST";
- }
-
- const char* getRequestURL() const {
- return "https://sp.example.org/SAML/POST";
- }
-
- const char* getQueryString() const {
- return NULL;
- }
};
public SAMLBindingBaseTestCase, public MessageEncoder::ArtifactGenerator, public MessageDecoder::ArtifactResolver {
public:
void setUp() {
- m_fields.clear();
SAMLBindingBaseTestCase::setUp();
}
void tearDown() {
- m_fields.clear();
SAMLBindingBaseTestCase::tearDown();
}
SAMLConfig::getConfig().MessageEncoderManager.newPlugin(SAMLConstants::SAML20_BINDING_HTTP_ARTIFACT, NULL)
);
encoder->setArtifactGenerator(this);
- encoder->encode(m_fields,toSend.get(),"https://sp.example.org/","state",m_creds);
+ encoder->encode(*this,toSend.get(),"https://sp.example.org/SAML/Artifact","https://sp.example.org/","state",m_creds);
toSend.release();
// Decode message.
throw;
}
}
-
- const char* getMethod() const {
- return "GET";
- }
-
- const char* getRequestURL() const {
- return "https://sp.example.org/SAML/Artifact";
- }
-
- const char* getQueryString() const {
- return NULL;
- }
SAMLArtifact* generateSAML1Artifact(const char* relyingParty) const {
throw BindingException("Not implemented.");
class SAML2POSTTest : public CxxTest::TestSuite, public SAMLBindingBaseTestCase {
public:
void setUp() {
- m_fields.clear();
SAMLBindingBaseTestCase::setUp();
}
void tearDown() {
- m_fields.clear();
SAMLBindingBaseTestCase::tearDown();
}
toSend->setIssueInstant(time(NULL));
// Encode message.
+ auto_ptr_XMLCh lit1("MessageEncoder");
+ auto_ptr_XMLCh lit2("template");
+ path = data_path + "binding/template.html";
+ auto_ptr_XMLCh lit3(path.c_str());
+ DOMDocument* encoder_config = XMLToolingConfig::getConfig().getParser().newDocument();
+ XercesJanitor<DOMDocument> janitor2(encoder_config);
+ encoder_config->appendChild(encoder_config->createElementNS(NULL,lit1.get()));
+ encoder_config->getDocumentElement()->setAttributeNS(NULL,lit2.get(),lit3.get());
auto_ptr<MessageEncoder> encoder(
- SAMLConfig::getConfig().MessageEncoderManager.newPlugin(SAMLConstants::SAML20_BINDING_HTTP_POST, NULL)
+ SAMLConfig::getConfig().MessageEncoderManager.newPlugin(
+ SAMLConstants::SAML20_BINDING_HTTP_POST, encoder_config->getDocumentElement()
+ )
);
- encoder->encode(m_fields,toSend.get(),"https://sp.example.org/","state",m_creds);
+ encoder->encode(*this,toSend.get(),"https://sp.example.org/SAML/POST","https://sp.example.org/","state",m_creds);
toSend.release();
// Decode message.
toSend->setID(NULL);
// Encode message.
+ auto_ptr_XMLCh lit1("MessageEncoder");
+ auto_ptr_XMLCh lit2("template");
+ path = data_path + "binding/template.html";
+ auto_ptr_XMLCh lit3(path.c_str());
+ DOMDocument* encoder_config = XMLToolingConfig::getConfig().getParser().newDocument();
+ XercesJanitor<DOMDocument> janitor2(encoder_config);
+ encoder_config->appendChild(encoder_config->createElementNS(NULL,lit1.get()));
+ encoder_config->getDocumentElement()->setAttributeNS(NULL,lit2.get(),lit3.get());
auto_ptr<MessageEncoder> encoder(
- SAMLConfig::getConfig().MessageEncoderManager.newPlugin(SAMLConstants::SAML20_BINDING_HTTP_POST, NULL)
+ SAMLConfig::getConfig().MessageEncoderManager.newPlugin(
+ SAMLConstants::SAML20_BINDING_HTTP_POST, encoder_config->getDocumentElement()
+ )
);
- encoder->encode(m_fields,toSend.get(),"https://sp.example.org/","state");
+ encoder->encode(*this,toSend.get(),"https://sp.example.org/SAML/POST","https://sp.example.org/","state");
toSend.release();
// Decode message.
throw;
}
}
-
- const char* getMethod() const {
- return "POST";
- }
-
- const char* getRequestURL() const {
- return "https://sp.example.org/SAML/POST";
- }
-
- const char* getQueryString() const {
- return NULL;
- }
};
#include <saml/SAMLConfig.h>
#include <saml/binding/ArtifactMap.h>
#include <xmltooling/util/ReplayCache.h>
+#include <xmltooling/util/TemplateEngine.h>
//#define SAML_LEAKCHECK
if (!SAMLConfig::getConfig().init())
return false;
XMLToolingConfig::getConfig().setReplayCache(new ReplayCache());
+ XMLToolingConfig::getConfig().setTemplateEngine(new TemplateEngine());
SAMLConfig::getConfig().setArtifactMap(new ArtifactMap());
if (getenv("SAMLTEST_DATA"))
</FileConfiguration>\r
</File>\r
<File\r
- RelativePath=".\binding.h"\r
- >\r
- </File>\r
- <File\r
- RelativePath=".\internal.h"\r
- >\r
- </File>\r
- <File\r
RelativePath=".\SAMLArtifactCreationTest.h"\r
>\r
<FileConfiguration\r
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"\r
>\r
</Filter>\r
+ <File\r
+ RelativePath=".\binding.h"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath=".\internal.h"\r
+ >\r
+ </File>\r
</Files>\r
<Globals>\r
</Globals>\r