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.
51 /* AAP.cpp - XML AAP implementation
61 #include <log4cpp/Category.hh>
63 using namespace shibboleth;
65 using namespace log4cpp;
68 #include <xercesc/framework/URLInputSource.hpp>
69 #include <xercesc/util/regx/RegularExpression.hpp>
71 AAP::AAP(const char* uri)
74 Category& log=Category::getInstance(SHIB_LOGCAT".AAP");
77 DOMDocument* doc=NULL;
80 static XMLCh base[]={chLatin_f, chLatin_i, chLatin_l, chLatin_e, chColon, chForwardSlash, chForwardSlash, chForwardSlash, chNull};
81 URLInputSource src(base,uri);
82 Wrapper4InputSource dsrc(&src,false);
85 log.infoStream() << "Loaded and parsed AAP (" << uri << ")" << CategoryStream::ENDLINE;
87 DOMElement* e = doc->getDocumentElement();
88 if (XMLString::compareString(XML::SHIB_NS,e->getNamespaceURI()) ||
89 XMLString::compareString(XML::Literals::AttributeAcceptancePolicy,e->getLocalName()))
91 log.error("Construction requires a valid AAP file: (shib:AttributeAcceptancePolicy as root element)");
92 throw MalformedException("Construction requires a valid site file: (shib:AttributeAcceptancePolicy as root element)");
95 // Loop over the AttributeRule elements.
96 DOMNodeList* nlist = e->getElementsByTagNameNS(XML::SHIB_NS,XML::Literals::AttributeRule);
97 for (int i=0; nlist && i<nlist->getLength(); i++)
99 // Insert an empty rule, then get a reference to it.
100 m_attrMap[static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,XML::Literals::Name)]=AttributeRule();
101 AttributeRule& arule=m_attrMap[static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,XML::Literals::Name)];
103 // Check for an AnySite rule.
104 DOMNode* anysite = nlist->item(i)->getFirstChild();
105 while (anysite && anysite->getNodeType()!=DOMNode::ELEMENT_NODE)
107 anysite = anysite->getNextSibling();
111 if (anysite && !XMLString::compareString(XML::SHIB_NS,static_cast<DOMElement*>(anysite)->getNamespaceURI()) &&
112 !XMLString::compareString(XML::Literals::AnySite,static_cast<DOMElement*>(anysite)->getLocalName()))
114 // Check for an AnyValue rule.
115 DOMNode* anyval = anysite->getFirstChild();
116 while (anyval && anyval->getNodeType()!=DOMNode::ELEMENT_NODE)
118 anyval = anyval->getNextSibling();
122 if (anyval && !XMLString::compareString(XML::SHIB_NS,static_cast<DOMElement*>(anyval)->getNamespaceURI()) &&
123 !XMLString::compareString(XML::Literals::AnyValue,static_cast<DOMElement*>(anyval)->getLocalName()))
125 arule.m_anySiteRule.anyValue=true;
129 // Process each Value element.
130 DOMNodeList* vlist = static_cast<DOMElement*>(anysite)->getElementsByTagNameNS(XML::SHIB_NS,XML::Literals::Value);
131 for (int j=0; vlist && j<vlist->getLength(); j++)
133 DOMElement* ve=static_cast<DOMElement*>(vlist->item(j));
134 DOMNode* valnode=ve->getFirstChild();
135 if (valnode && valnode->getNodeType()==DOMNode::TEXT_NODE)
137 if (!XMLString::compareString(XML::Literals::literal,ve->getAttributeNS(NULL,XML::Literals::Type)))
138 arule.m_anySiteRule.valueRules.push_back(
139 pair<AttributeRule::value_type,xstring>(AttributeRule::literal,valnode->getNodeValue())
141 else if (!XMLString::compareString(XML::Literals::regexp,ve->getAttributeNS(NULL,XML::Literals::Type)))
142 arule.m_anySiteRule.valueRules.push_back(
143 pair<AttributeRule::value_type,xstring>(AttributeRule::regexp,valnode->getNodeValue())
145 else if (!XMLString::compareString(XML::Literals::xpath,ve->getAttributeNS(NULL,XML::Literals::Type)))
146 arule.m_anySiteRule.valueRules.push_back(
147 pair<AttributeRule::value_type,xstring>(AttributeRule::xpath,valnode->getNodeValue())
154 // Loop over the SiteRule elements.
155 DOMNodeList* slist = static_cast<DOMElement*>(nlist->item(i))->getElementsByTagNameNS(XML::SHIB_NS,XML::Literals::SiteRule);
156 for (int k=0; slist && k<slist->getLength(); k++)
158 arule.m_siteMap[static_cast<DOMElement*>(slist->item(k))->getAttributeNS(NULL,XML::Literals::Name)]=AttributeRule::SiteRule();
159 AttributeRule::SiteRule& srule=arule.m_siteMap[static_cast<DOMElement*>(slist->item(k))->getAttributeNS(NULL,XML::Literals::Name)];
161 // Check for an AnyValue rule.
162 DOMNode* anyval = slist->item(k)->getFirstChild();
163 while (anyval && anyval->getNodeType()!=DOMNode::ELEMENT_NODE)
165 anyval = anyval->getNextSibling();
169 if (anyval && !XMLString::compareString(XML::SHIB_NS,static_cast<DOMElement*>(anyval)->getNamespaceURI()) &&
170 !XMLString::compareString(XML::Literals::AnyValue,static_cast<DOMElement*>(anyval)->getLocalName()))
176 // Process each Value element.
177 DOMNodeList* vlist = static_cast<DOMElement*>(slist->item(k))->getElementsByTagNameNS(XML::SHIB_NS,XML::Literals::Value);
178 for (int j=0; vlist && j<vlist->getLength(); j++)
180 DOMElement* ve=static_cast<DOMElement*>(vlist->item(j));
181 DOMNode* valnode=ve->getFirstChild();
182 if (valnode && valnode->getNodeType()==DOMNode::TEXT_NODE)
184 if (!XMLString::compareString(XML::Literals::literal,ve->getAttributeNS(NULL,XML::Literals::Type)))
185 srule.valueRules.push_back(
186 pair<AttributeRule::value_type,xstring>(AttributeRule::literal,valnode->getNodeValue())
188 else if (!XMLString::compareString(XML::Literals::regexp,ve->getAttributeNS(NULL,XML::Literals::Type)))
189 srule.valueRules.push_back(
190 pair<AttributeRule::value_type,xstring>(AttributeRule::regexp,valnode->getNodeValue())
192 else if (!XMLString::compareString(XML::Literals::xpath,ve->getAttributeNS(NULL,XML::Literals::Type)))
193 srule.valueRules.push_back(
194 pair<AttributeRule::value_type,xstring>(AttributeRule::xpath,valnode->getNodeValue())
202 catch (SAMLException& e)
204 log.errorStream() << "XML error while parsing AAP: " << e.what() << CategoryStream::ENDLINE;
211 log.error("Unexpected error while parsing AAP");
219 bool AAP::accept(const XMLCh* name, const XMLCh* originSite, DOMElement* e)
222 log4cpp::Category& log=log4cpp::Category::getInstance(SHIB_LOGCAT".AAP");
224 if (log.isDebugEnabled())
226 auto_ptr<char> temp(XMLString::transcode(name));
227 auto_ptr<char> temp2(XMLString::transcode(originSite));
228 log.debug("evaluating value for attribute '%s' from site '%s'",temp.get(),temp2.get());
231 map<xstring,AttributeRule>::const_iterator arule=m_attrMap.find(name);
232 if (arule==m_attrMap.end())
234 log.warn("attribute not found in AAP, any value is rejected");
238 // Don't currently support non-simple content models...
239 DOMNode* n=e->getFirstChild();
240 if (!n || n->getNodeType()!=DOMNode::TEXT_NODE)
242 log.warn("implementation does not support complex attribute values");
246 if (arule->second.m_anySiteRule.anyValue)
248 log.debug("any site, any value, match");
252 for (vector<pair<AttributeRule::value_type,xstring> >::const_iterator i=arule->second.m_anySiteRule.valueRules.begin();
253 i!=arule->second.m_anySiteRule.valueRules.end(); i++)
255 if (i->first==AttributeRule::literal)
257 if (i->second==n->getNodeValue())
259 log.debug("any site, literal match");
263 else if (i->first==AttributeRule::regexp)
267 RegularExpression re(i->second.c_str());
268 if (re.matches(n->getNodeValue()))
270 log.debug("any site, regexp match");
274 catch (XMLException& ex)
276 auto_ptr<char> tmp(XMLString::transcode(ex.getMessage()));
277 log.errorStream() << "caught exception while parsing regular expression: " << tmp.get()
278 << log4cpp::CategoryStream::ENDLINE;
282 log.warn("implementation does not support XPath value rules");
285 map<xstring,AttributeRule::SiteRule>::const_iterator srule=arule->second.m_siteMap.find(originSite);
286 if (srule==arule->second.m_siteMap.end())
288 log.warn("site not found in attribute ruleset, any value is rejected");
292 if (srule->second.anyValue)
294 log.debug("matching site, any value, match");
298 for (vector<pair<AttributeRule::value_type,xstring> >::const_iterator j=srule->second.valueRules.begin();
299 j!=srule->second.valueRules.end(); j++)
301 if (j->first==AttributeRule::literal)
303 if (j->second==n->getNodeValue())
305 log.debug("matching site, literal match");
309 else if (j->first==AttributeRule::regexp)
313 RegularExpression re(j->second.c_str());
314 if (re.matches(n->getNodeValue()))
316 log.debug("matching site, regexp match");
320 catch (XMLException& ex)
322 auto_ptr<char> tmp(XMLString::transcode(ex.getMessage()));
323 log.errorStream() << "caught exception while parsing regular expression: " << tmp.get()
324 << log4cpp::CategoryStream::ENDLINE;
328 log.warn("implementation does not support XPath value rules");
331 log.warn("attribute value could not be validated by AAP, rejecting it");