X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=saml%2Fsaml2%2Fbinding%2Fimpl%2FSAML2POSTEncoder.cpp;h=7d388fd6052c485d61b6b17ba7c68827afab3f5b;hb=1462057b3b9ae7e165d34d988e30b14c213672ca;hp=efa5a57a444a0b7e87e6dcf838ef72cce1bb4077;hpb=5d4b679f292a46494e822e9634f0ffa06f8f421c;p=shibboleth%2Fcpp-opensaml.git diff --git a/saml/saml2/binding/impl/SAML2POSTEncoder.cpp b/saml/saml2/binding/impl/SAML2POSTEncoder.cpp index efa5a57..7d388fd 100644 --- a/saml/saml2/binding/impl/SAML2POSTEncoder.cpp +++ b/saml/saml2/binding/impl/SAML2POSTEncoder.cpp @@ -1,23 +1,27 @@ -/* - * Copyright 2001-2007 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 +/** + * Licensed to the University Corporation for Advanced Internet + * Development, Inc. (UCAID) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. * - * http://www.apache.org/licenses/LICENSE-2.0 + * UCAID licenses this file to you 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 * - * 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. + * 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. */ /** * SAML2POSTEncoder.cpp * - * SAML 2.0 HTTP-POST binding message encoder + * SAML 2.0 HTTP-POST binding message encoder. */ #include "internal.h" @@ -28,17 +32,24 @@ #include #include -#include #include +#include +#include +#include +#include +#include +#include +#include #include +#include #include using namespace opensaml::saml2p; using namespace opensaml::saml2md; using namespace opensaml; using namespace xmlsignature; +using namespace xmltooling::logging; using namespace xmltooling; -using namespace log4cpp; using namespace std; namespace opensaml { @@ -46,18 +57,23 @@ namespace opensaml { class SAML_DLLLOCAL SAML2POSTEncoder : public MessageEncoder { public: - SAML2POSTEncoder(const DOMElement* e, bool simple=false); + SAML2POSTEncoder(const DOMElement* e, const XMLCh* ns, bool simple=false); virtual ~SAML2POSTEncoder() {} - + + const XMLCh* getProtocolFamily() const { + return samlconstants::SAML20P_NS; + } + long encode( GenericResponse& genericResponse, XMLObject* xmlObject, const char* destination, - const EntityDescriptor* recipient=NULL, - const char* relayState=NULL, - const Credential* credential=NULL, - const XMLCh* signatureAlg=NULL, - const XMLCh* digestAlg=NULL + const EntityDescriptor* recipient=nullptr, + const char* relayState=nullptr, + const ArtifactGenerator* artifactGenerator=nullptr, + const Credential* credential=nullptr, + const XMLCh* signatureAlg=nullptr, + const XMLCh* digestAlg=nullptr ) const; private: @@ -65,29 +81,26 @@ namespace opensaml { bool m_simple; }; - MessageEncoder* SAML_DLLLOCAL SAML2POSTEncoderFactory(const DOMElement* const & e) + MessageEncoder* SAML_DLLLOCAL SAML2POSTEncoderFactory(const pair& p) { - return new SAML2POSTEncoder(e, false); + return new SAML2POSTEncoder(p.first, p.second, false); } - MessageEncoder* SAML_DLLLOCAL SAML2POSTSimpleSignEncoderFactory(const DOMElement* const & e) + MessageEncoder* SAML_DLLLOCAL SAML2POSTSimpleSignEncoderFactory(const pair& p) { - return new SAML2POSTEncoder(e, true); + return new SAML2POSTEncoder(p.first, p.second, true); } }; }; static const XMLCh _template[] = UNICODE_LITERAL_8(t,e,m,p,l,a,t,e); -SAML2POSTEncoder::SAML2POSTEncoder(const DOMElement* e, bool simple) : m_simple(simple) +SAML2POSTEncoder::SAML2POSTEncoder(const DOMElement* e, const XMLCh* ns, bool simple) + : m_template(XMLHelper::getAttrString(e, "bindingTemplate.html", _template, ns)), m_simple(simple) { - if (e) { - auto_ptr_char t(e->getAttributeNS(NULL, _template)); - if (t.get()) - m_template = t.get(); - } if (m_template.empty()) throw XMLToolingException("SAML2POSTEncoder requires template XML attribute."); + XMLToolingConfig::getConfig().getPathResolver()->resolve(m_template, PathResolver::XMLTOOLING_CFG_FILE); } long SAML2POSTEncoder::encode( @@ -96,6 +109,7 @@ long SAML2POSTEncoder::encode( const char* destination, const EntityDescriptor* recipient, const char* relayState, + const ArtifactGenerator* artifactGenerator, const Credential* credential, const XMLCh* signatureAlg, const XMLCh* digestAlg @@ -104,13 +118,17 @@ long SAML2POSTEncoder::encode( #ifdef _DEBUG xmltooling::NDC ndc("encode"); #endif - Category& log = Category::getInstance(SAML_LOGCAT".MessageEncoder.SAML2POST"); - + Category& log = Category::getInstance(SAML_LOGCAT ".MessageEncoder.SAML2POST"); log.debug("validating input"); + + TemplateEngine* engine = XMLToolingConfig::getConfig().getTemplateEngine(); + if (!engine || !destination) + throw BindingException("Encoding message using POST requires a TemplateEngine instance and a destination."); + HTTPResponse::sanitizeURL(destination); if (xmlObject->getParent()) throw BindingException("Cannot encode XML content with parent."); - StatusResponseType* response = NULL; + StatusResponseType* response = nullptr; RequestAbstractType* request = dynamic_cast(xmlObject); if (!request) { response = dynamic_cast(xmlObject); @@ -118,7 +136,7 @@ long SAML2POSTEncoder::encode( throw BindingException("XML content for SAML 2.0 HTTP-POST Encoder must be a SAML 2.0 protocol message."); } - DOMElement* rootElement = NULL; + DOMElement* rootElement = nullptr; if (credential && !m_simple) { // Signature based on native XML signing. if (request ? request->getSignature() : response->getSignature()) { @@ -140,23 +158,20 @@ long SAML2POSTEncoder::encode( // Sign response while marshalling. vector sigs(1,sig); - rootElement = xmlObject->marshall((DOMDocument*)NULL,&sigs,credential); + rootElement = xmlObject->marshall((DOMDocument*)nullptr,&sigs,credential); } } else { log.debug("marshalling the message"); - rootElement = xmlObject->marshall((DOMDocument*)NULL); + rootElement = xmlObject->marshall((DOMDocument*)nullptr); } - // Start tracking data. - TemplateEngine::TemplateParameters pmap; - if (relayState && *relayState) - pmap.m_map["RelayState"] = relayState; - // Serialize the message. + TemplateEngine::TemplateParameters pmap; string& msg = pmap.m_map[(request ? "SAMLRequest" : "SAMLResponse")]; XMLHelper::serialize(rootElement, msg); - + log.debug("marshalled message:\n%s", msg.c_str()); + // SimpleSign. if (credential && m_simple) { log.debug("applying simple signature to message data"); @@ -173,29 +188,55 @@ long SAML2POSTEncoder::encode( memset(sigbuf,0,sizeof(sigbuf)); Signature::createRawSignature(credential->getPrivateKey(), signatureAlg, input.c_str(), input.length(), sigbuf, sizeof(sigbuf)-1); pmap.m_map["Signature"] = sigbuf; + + auto_ptr keyInfo(credential->getKeyInfo()); + if (keyInfo.get()) { + string& kstring = pmap.m_map["KeyInfo"]; + XMLHelper::serialize(keyInfo->marshall((DOMDocument*)nullptr), kstring); + xsecsize_t len=0; + XMLByte* out=Base64::encode(reinterpret_cast(kstring.data()),kstring.size(),&len); + if (!out) + throw BindingException("Base64 encoding of XML failed."); + kstring.erase(); + kstring.append(reinterpret_cast(out),len); +#ifdef OPENSAML_XERCESC_HAS_XMLBYTE_RELEASE + XMLString::release(&out); +#else + XMLString::release((char**)&out); +#endif + } } // Base64 the message. - unsigned int len=0; + xsecsize_t len=0; XMLByte* out=Base64::encode(reinterpret_cast(msg.data()),msg.size(),&len); if (!out) throw BindingException("Base64 encoding of XML failed."); msg.erase(); msg.append(reinterpret_cast(out),len); +#ifdef OPENSAML_XERCESC_HAS_XMLBYTE_RELEASE XMLString::release(&out); +#else + XMLString::release((char**)&out); +#endif - // Push message into template and send result to client. + // Push the rest of it 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())); pmap.m_map["action"] = destination; + if (relayState && *relayState) + pmap.m_map["RelayState"] = relayState; stringstream s; engine->run(infile, s, pmap); genericResponse.setContentType("text/html"); + HTTPResponse* httpResponse = dynamic_cast(&genericResponse); + if (httpResponse) { + httpResponse->setResponseHeader("Expires", "01-Jan-1997 12:00:00 GMT"); + httpResponse->setResponseHeader("Cache-Control", "no-cache, no-store, must-revalidate, private"); + httpResponse->setResponseHeader("Pragma", "no-cache"); + } long ret = genericResponse.sendResponse(s); // Cleanup by destroying XML.