+++ /dev/null
-/*
- * The Shibboleth License, Version 1.
- * Copyright (c) 2002
- * University Corporation for Advanced Internet Development, Inc.
- * All rights reserved
- *
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution, if any, must include
- * the following acknowledgment: "This product includes software developed by
- * the University Corporation for Advanced Internet Development
- * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement
- * may appear in the software itself, if and wherever such third-party
- * acknowledgments normally appear.
- *
- * Neither the name of Shibboleth nor the names of its contributors, nor
- * Internet2, nor the University Corporation for Advanced Internet Development,
- * Inc., nor UCAID may be used to endorse or promote products derived from this
- * software without specific prior written permission. For written permission,
- * please contact shibboleth@shibboleth.org
- *
- * Products derived from this software may not be called Shibboleth, Internet2,
- * UCAID, or the University Corporation for Advanced Internet Development, nor
- * may Shibboleth appear in their name, without prior written permission of the
- * University Corporation for Advanced Internet Development.
- *
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK
- * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE.
- * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY
- * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package edu.internet2.middleware.shibboleth.shire;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.security.Key;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletException;
-import javax.servlet.UnavailableException;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpUtils;
-
-import org.apache.log4j.Logger;
-import org.doomdark.uuid.UUIDGenerator;
-import org.opensaml.SAMLAuthenticationStatement;
-import org.opensaml.SAMLAssertion;
-import org.opensaml.SAMLException;
-import org.opensaml.SAMLResponse;
-import sun.misc.BASE64Decoder;
-
-import edu.internet2.middleware.shibboleth.common.Constants;
-import edu.internet2.middleware.shibboleth.common.OriginSiteMapperException;
-import edu.internet2.middleware.shibboleth.common.ShibPOSTProfile;
-import edu.internet2.middleware.shibboleth.common.ShibPOSTProfileFactory;
-
-/**
- * Implements a SAML POST profile consumer
- *
- * @author Scott Cantor
- * @created June 10, 2002
- */
-
-public class ShireServlet extends HttpServlet {
-
- private String shireLocation;
- private String cookieName;
- private String cookieDomain;
- private String sessionDir;
- private String keyStorePath;
- private String keyStorePasswd;
- private String keyStoreAlias;
- private String registryURI;
- private boolean sslOnly = true;
- private boolean checkAddress = true;
- private boolean verbose = false;
-
- private XMLOriginSiteMapper mapper = null;
- private static Logger log = Logger.getLogger(ShireServlet.class.getName());
-
- /**
- * Use the following servlet init parameters:<P>
- *
- *
- * <DL>
- * <DT> shire-location <I>(optional)</I> </DT>
- * <DD> The URL of the SHIRE if not derivable from requests</DD>
- * <DT> keystore-path <I>(required)</I> </DT>
- * <DD> A pathname to the trusted CA roots to accept</DD>
- * <DT> keystore-password <I>(required)</I> </DT>
- * <DD> The root keystore password</DD>
- * <DT> keystore-alias <I>(optional)</I> </DT>
- * <DD> An alias in the provided keystore for the cert that can verify
- * the origin site registry signature</DD>
- * <DT> registry-uri <I>(required)</I> </DT>
- * <DD> The origin site registry URI to install</DD>
- * <DT> cookie-name <I>(required)</I> </DT>
- * <DD> Name of session cookie to set in browser</DD>
- * <DT> cookie-domain <I>(optional)</I> </DT>
- * <DD> Domain of session cookie to set in browser</DD>
- * <DT> ssl-only <I>(defaults to true)</I> </DT>
- * <DD> If true, allow only SSL-protected POSTs and issue a secure cookie
- * </DD>
- * <DT> check-address <I>(defaults to true)</I> </DT>
- * <DD> If true, check client's IP address against assertion</DD>
- * <DT> session-dir <I>(defaults to /tmp)</I> </DT>
- * <DD> Directory in which to place session files</DD>
- * </DL>
- *
- */
- public void init() throws ServletException {
- super.init();
- log.info("Initializing SHIRE.");
-
- edu.internet2.middleware.shibboleth.common.Init.init();
-
- loadInitParams();
- verifyConfig();
-
- log.info("Loading keystore.");
- try {
- Key k = null;
- KeyStore ks = KeyStore.getInstance("JKS");
- ks.load(getServletContext().getResourceAsStream(keyStorePath), keyStorePasswd.toCharArray());
-
- log.debug("Configured to use keystore-alias (" + keyStoreAlias + ") to verify site file.");
- if (keyStoreAlias != null) {
- Certificate cert;
- cert = ks.getCertificate(keyStoreAlias);
-
- if (cert == null || (k = cert.getPublicKey()) == null) {
- log.fatal(
- "Unable to load registry verification certificate ("
- + keyStoreAlias
- + ") from keystore");
- throw new UnavailableException(
- "Unable to load registry verification certificate ("
- + keyStoreAlias
- + ") from keystore");
- }
- }
-
- log.info("Loading shibboleth site information.");
- mapper = new XMLOriginSiteMapper(registryURI, k, ks);
- log.info("Completed SHIRE initialization");
-
- } catch (OriginSiteMapperException e) {
- log.fatal("Configuration problem: Unable load shibboleth site information." + e);
- throw new UnavailableException(
- "Configuration problem: Unable load shibboleth site information." + e);
- } catch (KeyStoreException e) {
- log.fatal("Configuration problem: Unable to load supplied keystore." + e);
- throw new UnavailableException("Configuration problem: Unable load supplied keystore." + e);
- } catch (NoSuchAlgorithmException e) {
- log.fatal("Configuration problem: Unable to load supplied keystore." + e);
- throw new UnavailableException("Configuration problem: Unable load supplied keystore." + e);
- } catch (CertificateException e) {
- log.fatal("Configuration problem: Unable to load supplied keystore." + e);
- throw new UnavailableException("Configuration problem: Unable load supplied keystore." + e);
- } catch (IOException e) {
- log.fatal("Configuration problem: Unable to loadsupplied keystore." + e);
- throw new UnavailableException("Configuration problem: Unable load supplied keystore." + e);
- }
-
- }
-
- /**
- * Ensures that all required initialization attributes have been set.
- */
- private void verifyConfig() throws UnavailableException {
-
- if (cookieName == null) {
- log.fatal("Init parameter (cookie-name) is required in deployment descriptor.");
- throw new UnavailableException("Init parameter (cookie-name) is required in deployment descriptor.");
- }
-
- if (registryURI == null) {
- log.fatal("Init parameter (registry-uri) is required in deployment descriptor.");
- throw new UnavailableException("Init parameter (registry-uri) is required in deployment descriptor.");
- }
-
- if (keyStorePath == null) {
- log.fatal("Init parameter (keystore-path) is required in deployment descriptor.");
- throw new UnavailableException("Init parameter (keystore-path) is required in deployment descriptor.");
- }
-
- if (keyStorePasswd == null) {
- log.fatal("Init parameter (keystore-password) is required in deployment descriptor.");
- throw new UnavailableException("Init parameter (keystore-password) is required in deployment descriptor.");
- }
-
- }
-
- /**
- * Loads SHIRE configuration parameters. Sets default values as appropriate.
- */
- private void loadInitParams() {
-
- log.info("Loading configuration from deployment descriptor (web.xml).");
-
- shireLocation = getServletConfig().getInitParameter("shire-location");
- cookieDomain = getServletConfig().getInitParameter("cookie-domain");
- cookieName = getServletConfig().getInitParameter("cookie-name");
- keyStorePath = getServletConfig().getInitParameter("keystore-path");
- keyStorePasswd = getServletConfig().getInitParameter("keystore-password");
- keyStoreAlias = getServletConfig().getInitParameter("keystore-alias");
- registryURI = getServletConfig().getInitParameter("registry-uri");
-
- sessionDir = getServletConfig().getInitParameter("session-dir");
- if (sessionDir == null) {
- sessionDir = "/tmp";
- log.warn("No session-dir parameter found... using default location: (" + sessionDir + ").");
- }
-
- String temp = getServletConfig().getInitParameter("ssl-only");
- if (temp != null && (temp.equalsIgnoreCase("false") || temp.equals("0")))
- sslOnly = false;
-
- temp = getServletConfig().getInitParameter("check-address");
- if (temp != null && (temp.equalsIgnoreCase("false") || temp.equals("0")))
- checkAddress = false;
-
- }
-
- /**
- * Processes a sign-on submission<P>
- *
- *
- *
- * @param request HTTP request context
- * @param response HTTP response context
- * @exception IOException Thrown if an I/O error occurs
- * @exception ServletException Thrown if a servlet engine error occurs
- */
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws IOException, ServletException {
-
- try {
-
- log.info("Received a handle package.");
- log.debug("Target URL from client: " + request.getParameter("TARGET"));
- validateRequest(request);
-
- SAMLAuthenticationStatement s = processAssertion(request,response);
- if (s==null)
- return;
- shareSession(
- response,
- s.getSubject().getName(),
- s.getSubject().getNameQualifier(),
- System.currentTimeMillis(),
- request.getRemoteAddr(),
- s.getBindings()[0].getBinding(),
- s.getBindings()[0].getLocation());
-
- log.info("Redirecting to the requested resource: (" + request.getParameter("TARGET") + ").");
- response.sendRedirect(request.getParameter("TARGET"));
-
- } catch (ShireException se) {
- handleError(se, request, response);
- }
-
- }
-
- /**
- * Extracts a SAML Authentication Assertion from a POST request object and performs appropriate validity
- * checks on the same.
- *
- * @param request The <code>HttpServletRequest</code> object for the current request
- * @param response The <code>HttpServletResponse</code> object for the current request
- * @exception ShireException Thrown if any error is encountered parsing or validating the assertion
- * that is retreived from the request object.
- */
-
- private SAMLAuthenticationStatement processAssertion(HttpServletRequest request, HttpServletResponse response) throws ShireException {
-
- log.info("Processing SAML Assertion.");
- try {
- // Get a profile object using our specifics.
- String[] policies = { Constants.POLICY_CLUBSHIB };
- ShibPOSTProfile profile =
- ShibPOSTProfileFactory.getInstance(
- policies,
- mapper,
- (shireLocation != null) ? shireLocation : HttpUtils.getRequestURL(request).toString(),
- 300);
-
- if (log.isDebugEnabled()) {
- try {
- log.debug(
- "Dumping unparsed SAML Response:"
- + System.getProperty("line.separator")
- + new String(
- new BASE64Decoder().decodeBuffer(request.getParameter("SAMLResponse")),
- "UTF8"));
- } catch (IOException e) {
- log.error("Encountered an error while decoding SAMLReponse for loggin purposes.");
- }
- }
-
- // Try and accept the response...
- SAMLResponse r = profile.accept(request.getParameter("SAMLResponse").getBytes());
-
- // We've got a valid signed response we can trust (or the whole response was empty...)
-
- if (log.isDebugEnabled()) {
- ByteArrayOutputStream bytestr = new ByteArrayOutputStream();
- try {
- r.toStream(bytestr);
- } catch (IOException e) {
- log.error("Very Strange... problem converting SAMLResponse to a Stream for logging purposes.");
- }
-
- log.debug(
- "Dumping parsed SAML Response:" + System.getProperty("line.separator") + bytestr.toString());
- }
-
- // Get the assertion we need.
- SAMLAssertion a = profile.getSSOAssertion(r);
- if (a == null) {
- throw new ShireException("The assertion of your Shibboleth identity was missing or incompatible with the policies of this site.");
- }
-
- // Check for replay, in which case we just redirect to the target.
-
- if (!profile.checkReplayCache(a)) {
- log.debug("Detected a replayed assertion, forwarding to target");
- try {
- response.sendRedirect(request.getParameter("TARGET"));
- return null;
- } catch (IOException e) {
- throw new ShireException("Unable to redirect browser to target after detecting replay.");
- }
- }
-
- // Get the statement we need.
- SAMLAuthenticationStatement s = profile.getSSOStatement(a);
- if (s == null) {
- throw new ShireException("The assertion of your Shibboleth identity was missing or incompatible with the policies of this site.");
- }
-
- if (checkAddress) {
- log.debug("Running with client address checking enabled.");
- log.debug("Client Address from request: " + request.getRemoteAddr());
- log.debug("Client Address from assertion: " + s.getSubjectIP());
- if (s.getSubjectIP() == null || !s.getSubjectIP().equals(request.getRemoteAddr())) {
- throw new ShireException("The IP address provided by your origin site was either missing or did not match your current address. To correct this problem, you may need to bypass a local proxy server.");
- }
- } else {
- log.debug("Running with client address checking disabled.");
- }
-
- // All we really need is here...
- log.debug("Shibboleth Origin Site: " + s.getSubject().getNameQualifier());
- log.debug("Shibboleth Handle: " + s.getSubject().getName());
- log.debug("Shibboleth AA URL: " + s.getBindings()[0].getLocation());
- return s;
-
- } catch (SAMLException e) {
- throw new ShireException("Error processing SAML assertion: " + e);
- }
- }
-
- /**
- * Makes user information available to SHAR.
- *
- */
-
- private void shareSession(
- HttpServletResponse response,
- String handle,
- String domain,
- long currentTime,
- String clientAddress,
- String protocolBinding,
- String locationBinding)
- throws ShireException {
-
- log.info("Generating SHIR/SHAR shared data.");
- String filename = UUIDGenerator.getInstance().generateRandomBasedUUID().toString();
- log.debug("Created unique session identifier: " + filename);
-
- // Write session identifier to a file
- String pathname = null;
- if (sessionDir.endsWith(File.separator))
- pathname = sessionDir + filename;
- else
- pathname = sessionDir + File.separatorChar + filename;
- PrintWriter fout;
- try {
- log.debug("Writing session data to file: (" + pathname + ")");
- fout = new PrintWriter(new FileWriter(pathname));
-
- log.debug("Session Pathname: " + pathname);
-
- fout.println("Handle=" + handle);
- fout.println("Domain=" + domain);
- fout.println("PBinding0=" + protocolBinding);
- fout.println("LBinding0=" + locationBinding);
- fout.println("Time=" + currentTime / 1000);
- fout.println("ClientAddress=" + clientAddress);
- fout.println("EOF");
- fout.close();
-
- Cookie cookie = new Cookie(cookieName, filename);
- cookie.setPath("/");
- if (cookieDomain != null)
- cookie.setDomain(cookieDomain);
- log.debug(
- "Adding session identifier to browser cookie: ("
- + cookie.getDomain()
- + ":"
- + cookie.getName()
- + ")");
- response.addCookie(cookie);
-
- } catch (IOException e) {
- log.error("Unable to write session to file (" + filename + ") : " + e);
- throw new ShireException("Unable to share session with SHAR.");
- }
- }
-
- /**
- * Ensures that the POST request contains the necessary data elements
- *
- * @param request <code>The HttpServletRequest</code> object for the current request
- * @exception ShireException thrown if required POST data is missing
- */
-
- private void validateRequest(HttpServletRequest request) throws ShireException {
-
- log.info("Validating POST request properties.");
-
- if (sslOnly && !request.isSecure()) {
- throw new ShireException("Access to this site requires the use of SSL.");
- }
-
- if (request.getParameter("TARGET") == null || request.getParameter("TARGET").length() == 0) {
- throw new ShireException("Invalid data from HS: No target URL received.");
- }
-
- if (request.getParameter("SAMLResponse") == null
- || request.getParameter("SAMLResponse").length() == 0) {
- throw new ShireException("Invalid data from HS: No SAML Assertion included received.");
- }
-
- }
-
- /**
- * Appropriately routes all recoverable errors encountered by the SHIRE
- */
-
- private void handleError(ShireException se, HttpServletRequest req, HttpServletResponse res) {
- log.error(se);
- log.debug("Displaying error page.");
- req.setAttribute("errorText", se.toString());
- req.setAttribute("requestURL", req.getRequestURI().toString());
- RequestDispatcher rd = req.getRequestDispatcher("/shireerror.jsp");
-
- try {
- rd.forward(req, res);
- } catch (IOException ioe) {
- log.error("Problem trying to display SHIRE error page: " + ioe.toString());
- } catch (ServletException servletE) {
- log.error("Problem trying to display SHIRE error page: " + servletE.toString());
- }
- }
-}
+++ /dev/null
-/*
- * The Shibboleth License, Version 1.
- * Copyright (c) 2002
- * University Corporation for Advanced Internet Development, Inc.
- * All rights reserved
- *
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution, if any, must include
- * the following acknowledgment: "This product includes software developed by
- * the University Corporation for Advanced Internet Development
- * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement
- * may appear in the software itself, if and wherever such third-party
- * acknowledgments normally appear.
- *
- * Neither the name of Shibboleth nor the names of its contributors, nor
- * Internet2, nor the University Corporation for Advanced Internet Development,
- * Inc., nor UCAID may be used to endorse or promote products derived from this
- * software without specific prior written permission. For written permission,
- * please contact shibboleth@shibboleth.org
- *
- * Products derived from this software may not be called Shibboleth, Internet2,
- * UCAID, or the University Corporation for Advanced Internet Development, nor
- * may Shibboleth appear in their name, without prior written permission of the
- * University Corporation for Advanced Internet Development.
- *
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK
- * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE.
- * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY
- * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package edu.internet2.middleware.shibboleth.shire;
-
-import java.io.IOException;
-import java.security.Key;
-import java.security.KeyStore;
-import java.security.PublicKey;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Vector;
-
-import org.apache.log4j.Logger;
-import org.apache.xml.security.c14n.Canonicalizer;
-import org.apache.xml.security.exceptions.XMLSecurityException;
-import org.apache.xml.security.keys.KeyInfo;
-import org.apache.xml.security.signature.Reference;
-import org.apache.xml.security.signature.SignedInfo;
-import org.apache.xml.security.signature.XMLSignature;
-import org.apache.xml.security.transforms.Transforms;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.xml.sax.SAXException;
-
-import edu.internet2.middleware.shibboleth.common.OriginSiteMapper;
-import edu.internet2.middleware.shibboleth.common.OriginSiteMapperException;
-import edu.internet2.middleware.shibboleth.common.XML;
-
-/**
- * OriginSiteMapper implementation using an XML file to populate an in-memory
- * database from an optionally-signed XML file
- *
- * @author Scott Cantor
- * @created June 8, 2002
- */
-public class XMLOriginSiteMapper implements OriginSiteMapper {
-
- private HashMap originSites = null;
- private HashMap hsKeys = null;
- private KeyStore ks = null;
- private static Logger log = Logger.getLogger(XMLOriginSiteMapper.class.getName());
-
- /**
- * Constructor for the XMLOriginSiteMapper object
- *
- * @param registryURI Tells where to find/download origin
- * site registry file
- * @param verifyKey Optional key to verify signature with
- * @param ks Key store containing the trusted roots
- * to be used by SHIRE
- * @exception Exception Raised if the registry file cannot be
- * parsed and loaded
- */
-
- public XMLOriginSiteMapper(String registryURI, Key verifyKey, KeyStore ks)
- throws OriginSiteMapperException {
- this.ks = ks;
- originSites = new HashMap();
- hsKeys = new HashMap();
-
- try {
- Document doc=org.opensaml.XML.parserPool.parse(registryURI);
- log.info("Located site file (" +registryURI +").");
- Element e = doc.getDocumentElement();
- if (!XML.SHIB_NS.equals(e.getNamespaceURI()) || !"Sites".equals(e.getLocalName())) {
- log.error("Construction requires a valid site file: (shib:Sites as root element)");
- throw new OriginSiteMapperException("Construction requires a valid site file: (shib:Sites as root element)");
- }
-
- // Loop over the OriginSite elements.
- NodeList nlist = e.getElementsByTagNameNS(XML.SHIB_NS, "OriginSite");
- for (int i = 0; nlist != null && i < nlist.getLength(); i++) {
- String os_name = ((Element) nlist.item(i)).getAttributeNS(null, "Name").trim();
- if (os_name.length() == 0)
- continue;
-
- OriginSite os_obj = new OriginSite(os_name);
- originSites.put(os_name, os_obj);
-
- Node os_child = nlist.item(i).getFirstChild();
- while (os_child != null) {
- if (os_child.getNodeType() != Node.ELEMENT_NODE) {
- os_child = os_child.getNextSibling();
- continue;
- }
-
- // Process the various kinds of OriginSite children that we care about...
- if (XML.SHIB_NS.equals(os_child.getNamespaceURI())
- && "HandleService".equals(os_child.getLocalName())) {
- String hs_name = ((Element) os_child).getAttributeNS(null, "Name").trim();
- if (hs_name.length() > 0) {
- os_obj.handleServices.add(hs_name);
-
- // Check for KeyInfo.
- Node ki = os_child.getFirstChild();
- while (ki != null && ki.getNodeType() != Node.ELEMENT_NODE)
- ki = ki.getNextSibling();
- if (ki != null
- && org.opensaml.XML.XMLSIG_NS.equals(ki.getNamespaceURI())
- && "KeyInfo".equals(ki.getLocalName())) {
- try {
- KeyInfo kinfo = new KeyInfo((Element) ki, null);
- PublicKey pubkey = kinfo.getPublicKey();
- if (pubkey != null)
- hsKeys.put(hs_name, pubkey);
- } catch (XMLSecurityException exc) {
- }
- }
- }
- } else if (
- XML.SHIB_NS.equals(os_child.getNamespaceURI())
- && "Domain".equals(os_child.getLocalName())) {
- String dom = os_child.getFirstChild().getNodeValue().trim();
- if (dom.length() > 0)
- os_obj.domains.add(dom);
- }
- os_child = os_child.getNextSibling();
- }
- }
-
- if (verifyKey != null) {
- log.info("Initialized with a key: attempting to verify document signature.");
- validateSignature(verifyKey, e);
- } else {
- log.info("Initialized without key: skipping signature verification.");
- }
-
- } catch (SAXException e) {
- log.error("Problem parsing site configuration" + e);
- throw new OriginSiteMapperException("Problem parsing site configuration" + e);
- } catch (IOException e) {
- log.error("Problem accessing site configuration" + e);
- throw new OriginSiteMapperException("Problem accessing site configuration" + e);
- } catch (org.opensaml.SAMLException e) {
- log.error("Problem configuring parser: " + e);
- throw new OriginSiteMapperException("Problem configuring parser: " + e);
- }
- }
-
- private void validateSignature(Key verifyKey, Element e) throws OriginSiteMapperException {
-
- Node n = e.getLastChild();
- while (n != null && n.getNodeType() != Node.ELEMENT_NODE)
- n = n.getPreviousSibling();
-
- if (n != null
- && org.opensaml.XML.XMLSIG_NS.equals(n.getNamespaceURI())
- && "Signature".equals(n.getLocalName())) {
- log.info("Located signature in document... verifying.");
- try {
- XMLSignature sig = new XMLSignature((Element) n, null);
- if (sig.checkSignatureValue(verifyKey)) {
- // Now we verify that what is signed is what we expect.
- SignedInfo sinfo = sig.getSignedInfo();
- if (sinfo.getLength() == 1
- && (sinfo
- .getCanonicalizationMethodURI()
- .equals(Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS)
- || sinfo.getCanonicalizationMethodURI().equals(
- Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS))) {
- Reference ref = sinfo.item(0);
- if (ref.getURI() == null || ref.getURI().equals("")) {
- Transforms trans = ref.getTransforms();
- if (trans.getLength() == 1
- && trans.item(0).getURI().equals(Transforms.TRANSFORM_ENVELOPED_SIGNATURE))
- log.info("Signature verification successful.");
- return;
- }
- log.error(
- "Unable to verify signature on registry file: Unsupported dsig reference or transform data submitted with signature.");
- throw new OriginSiteMapperException("Unable to verify signature on registry file: Unsupported dsig reference or transform data submitted with signature.");
- } else {
- log.error(
- "Unable to verify signature on registry file: Unsupported canonicalization method.");
- throw new OriginSiteMapperException("Unable to verify signature on registry file: Unsupported canonicalization method.");
- }
- } else {
- log.error(
- "Unable to verify signature on registry file: signature cannot be verified with the specified key.");
- throw new OriginSiteMapperException("Unable to verify signature on registry file: signature cannot be verified with the specified key.");
- }
- } catch (Exception sigE) {
- log.error(
- "Unable to verify signature on registry file: An error occured while attempting to verify the signature:"
- + sigE);
- throw new OriginSiteMapperException(
- "Unable to verify signature on registry file: An error occured while attempting to verify the signature:"
- + sigE);
- }
- } else {
- log.error("Unable to verify signature on registry file: no signature found in document.");
- throw new OriginSiteMapperException("Unable to verify signature on registry file: no signature found in document.");
- }
-
- }
-
- /**
- * Provides an iterator over the trusted Handle Services for the specified
- * origin site
- *
- * @param originSite The DNS name of the origin site to query
- * @return An iterator over the Handle Service DNS names
- */
- public Iterator getHandleServiceNames(String originSite) {
- OriginSite o = (OriginSite) originSites.get(originSite);
- if (o != null)
- return o.handleServices.iterator();
- return null;
- }
-
- /**
- * Returns a preconfigured key to use in verifying a signature created by
- * the specified HS<P>
- *
- * Any key returned is implicitly trusted and a certificate signed by
- * another trusted entity is not sought or required
- *
- * @param handleService Description of Parameter
- * @return A trusted key (probably public but could be
- * secret) or null
- */
- public Key getHandleServiceKey(String handleService) {
- return (Key) hsKeys.get(handleService);
- }
-
- /**
- * Provides an iterator over the security domain expressions for which the
- * specified origin site is considered to be authoritative
- *
- * @param originSite The DNS name of the origin site to query
- * @return An iterator over a set of regular expression strings
- */
- public Iterator getSecurityDomains(String originSite) {
- OriginSite o = (OriginSite) originSites.get(originSite);
- if (o != null)
- return o.domains.iterator();
- return null;
- }
-
- /**
- * Gets a key store containing certificate entries that are trusted to sign
- * Handle Service certificates that are encountered during processing<P>
- *
- *
- *
- * @return A key store containing trusted certificate issuers
- */
- public KeyStore getTrustedRoots() {
- return ks;
- }
-
- private class OriginSite {
-
- private Vector domains = null;
- private Vector handleServices = null;
-
- private OriginSite(String name) {
- domains = new Vector();
- domains.add(name);
- handleServices = new Vector();
- }
- }
-}