*/
#include "internal.h"
+#include "Application.h"
#include "exceptions.h"
#include "ServiceProvider.h"
#include "binding/SOAPClient.h"
-#include <log4cpp/Category.hh>
#include <saml/saml2/metadata/Metadata.h>
#include <xmltooling/soap/SOAP.h>
#include <xmltooling/soap/HTTPSOAPTransport.h>
using namespace opensaml::saml2md;
using namespace xmlsignature;
using namespace xmltooling;
-using namespace log4cpp;
using namespace std;
-namespace {
- class SHIBSP_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);
- }
- };
-};
-
-SOAPClient::SOAPClient(const Application& application, opensaml::SecurityPolicy& policy)
- : opensaml::SOAPClient(policy), m_app(application), m_settings(NULL), m_credUse(NULL), m_credResolver(NULL)
+SOAPClient::SOAPClient(SecurityPolicy& policy)
+ : opensaml::SOAPClient(policy), m_app(policy.getApplication()), m_settings(NULL), m_relyingParty(NULL), m_credResolver(NULL)
{
- SPConfig& conf = SPConfig::getConfig();
- pair<bool,const char*> policyId = m_app.getString("policyId");
- m_settings = conf.getServiceProvider()->getPolicySettings(policyId.second);
- const vector<const opensaml::SecurityPolicyRule*>& rules = conf.getServiceProvider()->getPolicyRules(policyId.second);
- for (vector<const opensaml::SecurityPolicyRule*>::const_iterator rule=rules.begin(); rule!=rules.end(); ++rule)
- policy.addRule(*rule);
- policy.setMetadataProvider(application.getMetadataProvider());
- policy.setTrustEngine(application.getTrustEngine());
+ m_settings = m_app.getServiceProvider().getPolicySettings(m_app.getString("policyId").second);
+ pair<bool,bool> validate = m_settings->getBool("validate");
+ policy.setValidating(validate.first && validate.second);
+ setValidating(validate.first && validate.second);
}
-void SOAPClient::send(const soap11::Envelope& env, const KeyInfoSource& peer, const char* endpoint)
+void SOAPClient::send(const soap11::Envelope& env, const char* from, MetadataCredentialCriteria& to, const char* endpoint)
{
- if (!m_peer)
- m_peer = dynamic_cast<const RoleDescriptor*>(&peer);
-
- if (m_peer) {
- const EntityDescriptor* entity = m_peer ? dynamic_cast<const EntityDescriptor*>(m_peer->getParent()) : NULL;
- m_credUse = entity ? m_app.getCredentialUse(entity) : NULL;
- }
-
// Check for message signing requirements.
- if (m_credUse) {
- pair<bool,bool> flag = m_credUse->getBool("signRequests");
- if (flag.first && flag.second) {
- CredentialResolver* cr=NULL;
- pair<bool,const char*> cred = m_credUse->getString("Signing");
- if (cred.first && (cr=SPConfig::getConfig().getServiceProvider()->getCredentialResolver(cred.second))) {
- // Looks like we're supposed to sign, so check for message.
+ m_relyingParty = m_app.getRelyingParty(dynamic_cast<const EntityDescriptor*>(to.getRole().getParent()));
+ pair<bool,const char*> flag = m_relyingParty->getString("signing");
+ if (flag.first && (!strcmp(flag.second, "true") || !strcmp(flag.second, "back"))) {
+ m_credResolver=m_app.getCredentialResolver();
+ if (m_credResolver) {
+ m_credResolver->lock();
+ // Fill in criteria to use.
+ to.setUsage(Credential::SIGNING_CREDENTIAL);
+ pair<bool,const char*> keyName = m_relyingParty->getString("keyName");
+ if (keyName.first)
+ to.getKeyNames().insert(keyName.second);
+ pair<bool,const XMLCh*> sigalg = m_relyingParty->getXMLString("signingAlg");
+ if (sigalg.first)
+ to.setXMLAlgorithm(sigalg.second);
+ const Credential* cred = m_credResolver->resolve(&to);
+ // Reset criteria back.
+ to.setKeyAlgorithm(NULL);
+ to.setKeySize(0);
+
+ if (cred) {
+ // Check for message.
const vector<XMLObject*>& bodies=const_cast<const soap11::Body*>(env.getBody())->getUnknownXMLObjects();
if (!bodies.empty()) {
opensaml::SignableObject* msg = dynamic_cast<opensaml::SignableObject*>(bodies.front());
// Build a Signature.
Signature* sig = SignatureBuilder::buildSignature();
msg->setSignature(sig);
- pair<bool,const XMLCh*> alg = m_credUse->getXMLString("sigAlgorithm");
- if (alg.first)
- sig->setSignatureAlgorithm(alg.second);
- Locker locker(cr);
- sig->setSigningKey(cr->getKey());
-
- // Build KeyInfo.
- const vector<XSECCryptoX509*>& certs = cr->getCertificates();
- if (!certs.empty()) {
- KeyInfo* keyInfo=KeyInfoBuilder::buildKeyInfo();
- sig->setKeyInfo(keyInfo);
- X509Data* x509Data=X509DataBuilder::buildX509Data();
- keyInfo->getX509Datas().push_back(x509Data);
- for_each(certs.begin(),certs.end(),bind1st(_addcert(),x509Data));
- }
+ if (sigalg.first)
+ sig->setSignatureAlgorithm(sigalg.second);
+ sigalg = m_relyingParty->getXMLString("digestAlg");
+ if (sigalg.first)
+ dynamic_cast<opensaml::ContentReference*>(sig->getContentReference())->setDigestAlgorithm(sigalg.second);
// Sign it. The marshalling step in the base class should be a no-op.
vector<Signature*> sigs(1,sig);
- env.marshall((DOMDocument*)NULL,&sigs);
+ env.marshall((DOMDocument*)NULL,&sigs,cred);
}
}
}
+ else {
+ Category::getInstance(SHIBSP_LOGCAT".SOAPClient").error("no signing credential supplied, leaving unsigned.");
+ }
+ }
+ else {
+ Category::getInstance(SHIBSP_LOGCAT".SOAPClient").error("no CredentialResolver available, leaving unsigned.");
}
}
- opensaml::SOAPClient::send(env, peer, endpoint);
+ opensaml::SOAPClient::send(env, from, to, endpoint);
}
void SOAPClient::prepareTransport(SOAPTransport& transport)
opensaml::SOAPClient::prepareTransport(transport);
- if (!m_credUse) {
- const EntityDescriptor* entity = m_peer ? dynamic_cast<const EntityDescriptor*>(m_peer->getParent()) : NULL;
- m_credUse = entity ? m_app.getCredentialUse(entity) : NULL;
- }
- if (m_credUse) {
- pair<bool,const char*> authType=m_credUse->getString("authType");
- if (authType.first) {
- SOAPTransport::transport_auth_t type=SOAPTransport::transport_auth_none;
- pair<bool,const char*> username=m_credUse->getString("authUsername");
- pair<bool,const char*> password=m_credUse->getString("authPassword");
- if (!username.first || !password.first)
- log.error("transport authType (%s) specified but authUsername or authPassword was missing", authType.second);
- else if (!strcmp(authType.second,"basic"))
- type = SOAPTransport::transport_auth_basic;
- else if (!strcmp(authType.second,"digest"))
- type = SOAPTransport::transport_auth_digest;
- else if (!strcmp(authType.second,"ntlm"))
- type = SOAPTransport::transport_auth_ntlm;
- else if (!strcmp(authType.second,"gss"))
- type = SOAPTransport::transport_auth_gss;
- else
- log.error("unknown authType (%s) specified in CredentialUse element", authType.second);
- if (type > SOAPTransport::transport_auth_none) {
- if (transport.setAuth(type,username.second,password.second))
- log.debug("configured for transport authentication (method=%s, username=%s)", authType.second, username.second);
- else
- log.error("failed to configure transport authentication (method=%s)", authType.second);
- }
- }
-
- authType = m_credUse->getString("TLS");
- if (authType.first) {
- m_credResolver = SPConfig::getConfig().getServiceProvider()->getCredentialResolver(authType.second);
- if (m_credResolver) {
+ pair<bool,const char*> authType=m_relyingParty->getString("authType");
+ if (!authType.first || !strcmp(authType.second,"TLS")) {
+ if (!m_credResolver) {
+ m_credResolver = m_app.getCredentialResolver();
+ if (m_credResolver)
m_credResolver->lock();
- if (!transport.setCredentialResolver(m_credResolver)) {
- m_credResolver->unlock();
- m_credResolver = NULL;
- log.error("failed to load CredentialResolver into SOAPTransport");
- }
+ }
+ if (m_credResolver) {
+ m_criteria->setUsage(Credential::TLS_CREDENTIAL);
+ authType = m_relyingParty->getString("keyName");
+ if (authType.first)
+ m_criteria->getKeyNames().insert(authType.second);
+ const Credential* cred = m_credResolver->resolve(m_criteria);
+ if (cred) {
+ if (!transport.setCredential(cred))
+ log.error("failed to load Credential into SOAPTransport");
}
else {
- log.error("unable to access CredentialResolver (%s)", authType.second);
+ log.error("no TLS credential supplied");
}
}
- }
-
+ else {
+ log.error("no CredentialResolver available for TLS");
+ }
+ }
+ else {
+ SOAPTransport::transport_auth_t type=SOAPTransport::transport_auth_none;
+ pair<bool,const char*> username=m_relyingParty->getString("authUsername");
+ pair<bool,const char*> password=m_relyingParty->getString("authPassword");
+ if (!username.first || !password.first)
+ log.error("transport authType (%s) specified but authUsername or authPassword was missing", authType.second);
+ else if (!strcmp(authType.second,"basic"))
+ type = SOAPTransport::transport_auth_basic;
+ else if (!strcmp(authType.second,"digest"))
+ type = SOAPTransport::transport_auth_digest;
+ else if (!strcmp(authType.second,"ntlm"))
+ type = SOAPTransport::transport_auth_ntlm;
+ else if (!strcmp(authType.second,"gss"))
+ type = SOAPTransport::transport_auth_gss;
+ else
+ log.error("unknown authType (%s) specified for RelyingParty", authType.second);
+ if (type > SOAPTransport::transport_auth_none) {
+ if (transport.setAuth(type,username.second,password.second))
+ log.debug("configured for transport authentication (method=%s, username=%s)", authType.second, username.second);
+ else
+ log.error("failed to configure transport authentication (method=%s)", authType.second);
+ }
+ }
+
transport.setConnectTimeout(m_settings->getUnsignedInt("connectTimeout").second);
transport.setTimeout(m_settings->getUnsignedInt("timeout").second);
+ m_app.getServiceProvider().setTransportOptions(m_app.getString("policyId").second, transport);
HTTPSOAPTransport* http = dynamic_cast<HTTPSOAPTransport*>(&transport);
if (http) {
flag = m_settings->getBool("chunkedEncoding");
http->useChunkedEncoding(!flag.first || flag.second);
- http->setRequestHeader("Shibboleth", PACKAGE_VERSION);
+ http->setRequestHeader("User-Agent", PACKAGE_NAME);
+ http->setRequestHeader(PACKAGE_NAME, PACKAGE_VERSION);
}
}
void SOAPClient::reset()
{
- m_credUse = NULL;
+ m_relyingParty = NULL;
if (m_credResolver)
m_credResolver->unlock();
m_credResolver = NULL;
opensaml::SOAPClient::reset();
-}
\ No newline at end of file
+}
+