372d33442c9d5b96e712aa0178744569476b8520
[shibboleth/sp.git] / shib / XMLOriginSiteMapper.cpp
1 /* 
2  * The Shibboleth License, Version 1. 
3  * Copyright (c) 2002 
4  * University Corporation for Advanced Internet Development, Inc. 
5  * All rights reserved
6  * 
7  * 
8  * Redistribution and use in source and binary forms, with or without 
9  * modification, are permitted provided that the following conditions are met:
10  * 
11  * Redistributions of source code must retain the above copyright notice, this 
12  * list of conditions and the following disclaimer.
13  * 
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.
22  * 
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
28  * 
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.
33  * 
34  * 
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.
48  */
49
50 /* XMLOriginSiteMapper.h - a mapper implementation that uses an XML-based registry
51
52    Scott Cantor
53    9/27/02
54
55    $History:$
56 */
57
58 #ifdef WIN32
59 # define SHIB_EXPORTS __declspec(dllexport)
60 #endif
61
62 #include <shib.h>
63 #include <log4cpp/Category.hh>
64 using namespace shibboleth;
65 using namespace saml;
66 using namespace log4cpp;
67 using namespace std;
68
69 #include <xercesc/framework/URLInputSource.hpp>
70
71 XMLOriginSiteMapper::XMLOriginSiteMapper(const char* registryURI,
72                                          const Iterator<X509Certificate*>& roots,
73                                          Key* verifyKey)
74 {
75     NDC ndc("XMLOriginSiteMapper");
76     Category& log=Category::getInstance(SHIB_LOGCAT".XMLOriginSiteMapper");
77
78     saml::XML::Parser p;
79     DOMDocument* doc=NULL;
80         try
81     {
82         URLInputSource src(NULL,registryURI);
83         Wrapper4InputSource dsrc(&src,false);
84                 doc=p.parse(dsrc);
85
86         log.infoStream() << "Loaded and parsed site file (" << registryURI << ")"
87             << CategoryStream::ENDLINE;
88
89                 DOMElement* e = doc->getDocumentElement();
90         if (XMLString::compareString(XML::SHIB_NS,e->getNamespaceURI()) ||
91             XMLString::compareString(XML::Literals::Sites,e->getLocalName()))
92         {
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)");
95                 }
96
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++)
100         {
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)
104                                 continue;
105
106                         OriginSite* os_obj = new OriginSite();
107                         m_sites[os_name.get()]=os_obj;
108
109                         DOMNode* os_child = nlist->item(i)->getFirstChild();
110                         while (os_child)
111             {
112                 if (os_child->getNodeType()!=DOMNode::ELEMENT_NODE)
113                 {
114                                         os_child = os_child->getNextSibling();
115                                         continue;
116                                 }
117
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()))
121                 {
122                     auto_ptr<XMLCh> hs_name(XMLString::replicate(static_cast<DOMElement*>(os_child)->getAttributeNS(NULL,XML::Literals::Name)));
123                     XMLString::trim(hs_name.get());
124
125                                         if (hs_name.get() && *hs_name)
126                     {
127                                                 os_obj->m_handleServices.push_back(hs_name.get());
128
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()))
135                         {
136                                                 }
137                         */
138                                         }
139                                 }
140                 else if (!XMLString::compareString(XML::SHIB_NS,os_child->getNamespaceURI()) &&
141                                              !XMLString::compareString(XML::Literals::Domain,os_child->getLocalName()))
142                 {
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());
147                                 }
148                                 os_child = os_child->getNextSibling();
149                         }
150                 }
151
152                 if (verifyKey)
153         {
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);
157                 }
158         else
159                         log.info("Initialized without key: skipping signature verification.");
160     }
161     catch (SAMLException& e)
162     {
163                 log.errorStream() << "XML error while parsing site configuration: " << e.what()
164             << CategoryStream::ENDLINE;
165         if (doc)
166             doc->release();
167                 throw;
168         }
169     catch (...)
170     {
171                 log.error("Unexpected error while parsing site configuration");
172         if (doc)
173             doc->release();
174                 throw;
175     }
176 }
177
178 XMLOriginSiteMapper::~XMLOriginSiteMapper()
179 {
180     for (map<xstring,OriginSite*>::iterator i=m_sites.begin(); i!=m_sites.end(); i++)
181         delete i->second;
182 }
183
184 /* TBD...
185 private void validateSignature(Key verifyKey, Element e) throws OriginSiteMapperException {
186
187         Node n = e.getLastChild();
188         while (n != null && n.getNodeType() != Node.ELEMENT_NODE)
189                 n = n.getPreviousSibling();
190
191         if (n != null
192                 && org.opensaml.XML.XMLSIG_NS.equals(n.getNamespaceURI())
193                 && "Signature".equals(n.getLocalName())) {
194                         log.info("Located signature in document... verifying.");
195                 try {
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
201                                         && (sinfo
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.");
212                                                         return;
213                                         }
214                                         log.error(
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.");
217                                 } else {
218                                         log.error(
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.");
221                                 }
222                         } else {
223                                 log.error(
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.");
226                         }
227                 } catch (Exception sigE) {
228                         log.error(
229                                 "Unable to verify signature on registry file: An error occured while attempting to verify the signature:"
230                                         + sigE);
231                         throw new OriginSiteMapperException(
232                                 "Unable to verify signature on registry file: An error occured while attempting to verify the signature:"
233                                         + sigE);
234                 }
235         } else {
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.");
238         }
239
240 }
241 */
242
243 Iterator<xstring> XMLOriginSiteMapper::getHandleServiceNames(const XMLCh* originSite)
244 {
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);
249 }
250
251 Key* XMLOriginSiteMapper::getHandleServiceKey(const XMLCh* handleService)
252 {
253     map<xstring,Key*>::const_iterator i=m_hsKeys.find(handleService);
254     return (i!=m_hsKeys.end()) ? i->second : NULL;
255 }
256
257 Iterator<xstring> XMLOriginSiteMapper::getSecurityDomains(const XMLCh* originSite)
258 {
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);
263 }
264
265 Iterator<X509Certificate*> XMLOriginSiteMapper::getTrustedRoots()
266 {
267         return Iterator<X509Certificate*>(m_roots);
268 }
269