2 * The Shibboleth License, Version 1.
4 * University Corporation for Advanced Internet Development, Inc.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
11 * Redistributions of source code must retain the above copyright notice, this
12 * list of conditions and the following disclaimer.
14 * Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution, if any, must include
17 * the following acknowledgment: "This product includes software developed by
18 * the University Corporation for Advanced Internet Development
19 * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement
20 * may appear in the software itself, if and wherever such third-party
21 * acknowledgments normally appear.
23 * Neither the name of Shibboleth nor the names of its contributors, nor
24 * Internet2, nor the University Corporation for Advanced Internet Development,
25 * Inc., nor UCAID may be used to endorse or promote products derived from this
26 * software without specific prior written permission. For written permission,
27 * please contact shibboleth@shibboleth.org
29 * Products derived from this software may not be called Shibboleth, Internet2,
30 * UCAID, or the University Corporation for Advanced Internet Development, nor
31 * may Shibboleth appear in their name, without prior written permission of the
32 * University Corporation for Advanced Internet Development.
35 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
36 * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
38 * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK
39 * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE.
40 * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY
41 * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT,
42 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
44 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
47 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
50 /* XMLOriginSiteMapper.h - a mapper implementation that uses an XML-based registry
59 # define SHIB_EXPORTS __declspec(dllexport)
63 #include <log4cpp/Category.hh>
64 using namespace shibboleth;
66 using namespace log4cpp;
69 #include <xercesc/framework/URLInputSource.hpp>
71 XMLOriginSiteMapper::XMLOriginSiteMapper(const char* registryURI,
72 const Iterator<X509Certificate*>& roots,
75 NDC ndc("XMLOriginSiteMapper");
76 Category& log=Category::getInstance(SHIB_LOGCAT".XMLOriginSiteMapper");
79 DOMDocument* doc=NULL;
82 URLInputSource src(NULL,registryURI);
83 Wrapper4InputSource dsrc(&src,false);
86 log.infoStream() << "Loaded and parsed site file (" << registryURI << ")"
87 << CategoryStream::ENDLINE;
89 DOMElement* e = doc->getDocumentElement();
90 if (XMLString::compareString(XML::SHIB_NS,e->getNamespaceURI()) ||
91 XMLString::compareString(XML::Literals::Sites,e->getLocalName()))
93 log.error("Construction requires a valid site file: (shib:Sites as root element)");
94 throw OriginSiteMapperException("Construction requires a valid site file: (shib:Sites as root element)");
97 // Loop over the OriginSite elements.
98 DOMNodeList* nlist = e->getElementsByTagNameNS(XML::SHIB_NS,XML::Literals::OriginSite);
99 for (int i=0; nlist && i<nlist->getLength(); i++)
101 auto_ptr<XMLCh> os_name(XMLString::replicate(static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,XML::Literals::Name)));
102 XMLString::trim(os_name.get());
103 if (!os_name.get() || !*os_name)
106 OriginSite* os_obj = new OriginSite();
107 m_sites[os_name.get()]=os_obj;
109 DOMNode* os_child = nlist->item(i)->getFirstChild();
112 if (os_child->getNodeType()!=DOMNode::ELEMENT_NODE)
114 os_child = os_child->getNextSibling();
118 // Process the various kinds of OriginSite children that we care about...
119 if (!XMLString::compareString(XML::SHIB_NS,os_child->getNamespaceURI()) &&
120 !XMLString::compareString(XML::Literals::HandleService,os_child->getLocalName()))
122 auto_ptr<XMLCh> hs_name(XMLString::replicate(static_cast<DOMElement*>(os_child)->getAttributeNS(NULL,XML::Literals::Name)));
123 XMLString::trim(hs_name.get());
125 if (hs_name.get() && *hs_name)
127 os_obj->m_handleServices.push_back(hs_name.get());
129 /* Ignore KeyInfo for now...
130 DOM*Node ki = os_child->getFirstChild();
131 while (ki && ki->getNodeType()!=DOMNode::ELEMENT_NODE)
132 ki = ki->getNextSibling();
133 if (ki && !XMLString::compareString(saml::XML::XMLSIG_NS,ki->getNamespaceURI()) &&
134 !XMLString::compareString(saml::XML::Literals::KeyInfo,ki->getNamespaceURI()))
140 else if (!XMLString::compareString(XML::SHIB_NS,os_child->getNamespaceURI()) &&
141 !XMLString::compareString(XML::Literals::Domain,os_child->getLocalName()))
143 auto_ptr<XMLCh> dom(XMLString::replicate(os_child->getFirstChild()->getNodeValue()));
144 XMLString::trim(dom.get());
145 if (dom.get() && *dom)
146 os_obj->m_domains.push_back(dom.get());
148 os_child = os_child->getNextSibling();
154 log.info("Initialized with a key: attempting to verify document signature.");
155 log.error("Signature verification not implemented yet, this may be a forged file!");
156 // validateSignature(verifyKey, e);
159 log.info("Initialized without key: skipping signature verification.");
161 catch (SAMLException& e)
163 log.errorStream() << "XML error while parsing site configuration: " << e.what()
164 << CategoryStream::ENDLINE;
171 log.error("Unexpected error while parsing site configuration");
178 XMLOriginSiteMapper::~XMLOriginSiteMapper()
180 for (map<xstring,OriginSite*>::iterator i=m_sites.begin(); i!=m_sites.end(); i++)
185 private void validateSignature(Key verifyKey, Element e) throws OriginSiteMapperException {
187 Node n = e.getLastChild();
188 while (n != null && n.getNodeType() != Node.ELEMENT_NODE)
189 n = n.getPreviousSibling();
192 && org.opensaml.XML.XMLSIG_NS.equals(n.getNamespaceURI())
193 && "Signature".equals(n.getLocalName())) {
194 log.info("Located signature in document... verifying.");
196 XMLSignature sig = new XMLSignature((Element) n, null);
197 if (sig.checkSignatureValue(verifyKey)) {
198 // Now we verify that what is signed is what we expect.
199 SignedInfo sinfo = sig.getSignedInfo();
200 if (sinfo.getLength() == 1
202 .getCanonicalizationMethodURI()
203 .equals(Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS)
204 || sinfo.getCanonicalizationMethodURI().equals(
205 Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS))) {
206 Reference ref = sinfo.item(0);
207 if (ref.getURI() == null || ref.getURI().equals("")) {
208 Transforms trans = ref.getTransforms();
209 if (trans.getLength() == 1
210 && trans.item(0).getURI().equals(Transforms.TRANSFORM_ENVELOPED_SIGNATURE))
211 log.info("Signature verification successful.");
215 "Unable to verify signature on registry file: Unsupported dsig reference or transform data submitted with signature.");
216 throw new OriginSiteMapperException("Unable to verify signature on registry file: Unsupported dsig reference or transform data submitted with signature.");
219 "Unable to verify signature on registry file: Unsupported canonicalization method.");
220 throw new OriginSiteMapperException("Unable to verify signature on registry file: Unsupported canonicalization method.");
224 "Unable to verify signature on registry file: signature cannot be verified with the specified key.");
225 throw new OriginSiteMapperException("Unable to verify signature on registry file: signature cannot be verified with the specified key.");
227 } catch (Exception sigE) {
229 "Unable to verify signature on registry file: An error occured while attempting to verify the signature:"
231 throw new OriginSiteMapperException(
232 "Unable to verify signature on registry file: An error occured while attempting to verify the signature:"
236 log.error("Unable to verify signature on registry file: no signature found in document.");
237 throw new OriginSiteMapperException("Unable to verify signature on registry file: no signature found in document.");
243 Iterator<xstring> XMLOriginSiteMapper::getHandleServiceNames(const XMLCh* originSite)
245 map<xstring,OriginSite*>::const_iterator i=m_sites.find(originSite);
246 if (i==m_sites.end())
247 return Iterator<xstring>();
248 return Iterator<xstring>(i->second->m_handleServices);
251 Key* XMLOriginSiteMapper::getHandleServiceKey(const XMLCh* handleService)
253 map<xstring,Key*>::const_iterator i=m_hsKeys.find(handleService);
254 return (i!=m_hsKeys.end()) ? i->second : NULL;
257 Iterator<xstring> XMLOriginSiteMapper::getSecurityDomains(const XMLCh* originSite)
259 map<xstring,OriginSite*>::const_iterator i=m_sites.find(originSite);
260 if (i==m_sites.end())
261 return Iterator<xstring>();
262 return Iterator<xstring>(i->second->m_domains);
265 Iterator<X509Certificate*> XMLOriginSiteMapper::getTrustedRoots()
267 return Iterator<X509Certificate*>(m_roots);