/* * reserved comment block * DO NOT REMOVE OR ALTER! */ /* * Copyright 1999-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations; import java.io.ByteArrayInputStream; import java.io.IOException; import java.security.PublicKey; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Set; import javax.xml.parsers.ParserConfigurationException; import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException; import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; import com.sun.org.apache.xml.internal.security.keys.content.RetrievalMethod; import com.sun.org.apache.xml.internal.security.keys.content.x509.XMLX509Certificate; import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolver; import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolverException; import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolverSpi; import com.sun.org.apache.xml.internal.security.keys.storage.StorageResolver; import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; import com.sun.org.apache.xml.internal.security.transforms.Transforms; import com.sun.org.apache.xml.internal.security.utils.Constants; import com.sun.org.apache.xml.internal.security.utils.XMLUtils; import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver; import org.w3c.dom.Attr; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.xml.sax.SAXException; /** * The RetrievalMethodResolver can retrieve public keys and certificates from * other locations. The location is specified using the ds:RetrievalMethod * element which points to the location. This includes the handling of raw * (binary) X.509 certificate which are not encapsulated in an XML structure. * If the retrieval process encounters an element which the * RetrievalMethodResolver cannot handle itself, resolving of the extracted * element is delegated back to the KeyResolver mechanism. * * @author $Author: mullan $ modified by Dave Garcia */ public class RetrievalMethodResolver extends KeyResolverSpi { /** {@link java.util.logging} logging facility */ static java.util.logging.Logger log = java.util.logging.Logger.getLogger( RetrievalMethodResolver.class.getName()); /** * Method engineResolvePublicKey * @inheritDoc * @param element * @param BaseURI * @param storage * */ public PublicKey engineLookupAndResolvePublicKey( Element element, String BaseURI, StorageResolver storage) { if (!XMLUtils.elementIsInSignatureSpace(element, Constants._TAG_RETRIEVALMETHOD)) { return null; } try { //Create a retrieval method over the given element RetrievalMethod rm = new RetrievalMethod(element, BaseURI); String type = rm.getType(); XMLSignatureInput resource=resolveInput(rm,BaseURI); if (RetrievalMethod.TYPE_RAWX509.equals(type)) { //a raw certificate, direct parsing is done! X509Certificate cert=getRawCertificate(resource); if (cert != null) { return cert.getPublicKey(); } return null; }; Element e = obtainRefrenceElement(resource); return resolveKey(e,BaseURI,storage); } catch (XMLSecurityException ex) { log.log(java.util.logging.Level.FINE, "XMLSecurityException", ex); } catch (CertificateException ex) { log.log(java.util.logging.Level.FINE, "CertificateException", ex); } catch (IOException ex) { log.log(java.util.logging.Level.FINE, "IOException", ex); } catch (ParserConfigurationException e) { log.log(java.util.logging.Level.FINE, "ParserConfigurationException", e); } catch (SAXException e) { log.log(java.util.logging.Level.FINE, "SAXException", e); } return null; } static private Element obtainRefrenceElement(XMLSignatureInput resource) throws CanonicalizationException, ParserConfigurationException, IOException, SAXException, KeyResolverException { Element e; if (resource.isElement()){ e=(Element) resource.getSubNode(); } else if (resource.isNodeSet()) { //Retrieved resource is a nodeSet e=getDocumentElement(resource.getNodeSet()); } else { //Retrieved resource is an inputStream byte inputBytes[] = resource.getBytes(); e = getDocFromBytes(inputBytes); //otherwise, we parse the resource, create an Element and delegate if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "we have to parse " + inputBytes.length + " bytes"); } return e; } /** * Method engineResolveX509Certificate * @inheritDoc * @param element * @param BaseURI * @param storage * */ public X509Certificate engineLookupResolveX509Certificate( Element element, String BaseURI, StorageResolver storage) { if (!XMLUtils.elementIsInSignatureSpace(element, Constants._TAG_RETRIEVALMETHOD)) { return null; } try { RetrievalMethod rm = new RetrievalMethod(element, BaseURI); String type = rm.getType(); XMLSignatureInput resource=resolveInput(rm,BaseURI); if (RetrievalMethod.TYPE_RAWX509.equals(type)) { X509Certificate cert=getRawCertificate(resource); return cert; } Element e = obtainRefrenceElement(resource); return resolveCertificate(e,BaseURI,storage); } catch (XMLSecurityException ex) { log.log(java.util.logging.Level.FINE, "XMLSecurityException", ex); } catch (CertificateException ex) { log.log(java.util.logging.Level.FINE, "CertificateException", ex); } catch (IOException ex) { log.log(java.util.logging.Level.FINE, "IOException", ex); } catch (ParserConfigurationException e) { log.log(java.util.logging.Level.FINE, "ParserConfigurationException", e); } catch (SAXException e) { log.log(java.util.logging.Level.FINE, "SAXException", e); } return null; } /** * Retrieves a x509Certificate from the given information * @param e * @param BaseURI * @param storage * @return * @throws KeyResolverException */ static private X509Certificate resolveCertificate(Element e,String BaseURI,StorageResolver storage) throws KeyResolverException{ if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Now we have a {" + e.getNamespaceURI() + "}"+ e.getLocalName() + " Element"); //An element has been provided if (e != null) { return KeyResolver.getX509Certificate(e,BaseURI, storage); } return null; } /** * Retrieves a x509Certificate from the given information * @param e * @param BaseURI * @param storage * @return * @throws KeyResolverException */ static private PublicKey resolveKey(Element e,String BaseURI,StorageResolver storage) throws KeyResolverException{ if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Now we have a {" + e.getNamespaceURI() + "}"+ e.getLocalName() + " Element"); //An element has been provided if (e != null) { return KeyResolver.getPublicKey(e,BaseURI, storage); } return null; } static private X509Certificate getRawCertificate(XMLSignatureInput resource) throws CanonicalizationException, IOException, CertificateException{ byte inputBytes[] = resource.getBytes(); // if the resource stores a raw certificate, we have to handle it CertificateFactory certFact =CertificateFactory.getInstance(XMLX509Certificate.JCA_CERT_ID); X509Certificate cert =(X509Certificate) certFact.generateCertificate(new ByteArrayInputStream(inputBytes)); return cert; } /** * Resolves the input from the given retrieval method * @return * @throws XMLSecurityException */ static private XMLSignatureInput resolveInput(RetrievalMethod rm,String BaseURI) throws XMLSecurityException{ Attr uri = rm.getURIAttr(); //Apply the trnasforms Transforms transforms = rm.getTransforms(); ResourceResolver resRes = ResourceResolver.getInstance(uri, BaseURI); if (resRes != null) { XMLSignatureInput resource = resRes.resolve(uri, BaseURI); if (transforms != null) { log.log(java.util.logging.Level.FINE, "We have Transforms"); resource = transforms.performTransforms(resource); } return resource; } return null; } /** * Parses a byte array and returns the parsed Element. * * @param bytes * @return the Document Element after parsing bytes * @throws KeyResolverException if something goes wrong */ static Element getDocFromBytes(byte[] bytes) throws KeyResolverException { try { javax.xml.parsers.DocumentBuilderFactory dbf =javax.xml.parsers.DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); javax.xml.parsers.DocumentBuilder db = dbf.newDocumentBuilder(); org.w3c.dom.Document doc = db.parse(new java.io.ByteArrayInputStream(bytes)); return doc.getDocumentElement(); } catch (org.xml.sax.SAXException ex) { throw new KeyResolverException("empty", ex); } catch (java.io.IOException ex) { throw new KeyResolverException("empty", ex); } catch (javax.xml.parsers.ParserConfigurationException ex) { throw new KeyResolverException("empty", ex); } } /** * Method engineResolveSecretKey * @inheritDoc * @param element * @param BaseURI * @param storage * */ public javax.crypto.SecretKey engineLookupAndResolveSecretKey( Element element, String BaseURI, StorageResolver storage) { return null; } static Element getDocumentElement(Set set) { Iterator it=set.iterator(); Element e=null; while (it.hasNext()) { Node currentNode=(Node)it.next(); if (currentNode instanceof Element) { e=(Element)currentNode; break; } } List parents=new ArrayList(10); //Obtain all the parents of the elemnt do { parents.add(e); Node n=e.getParentNode(); if (!(n instanceof Element )) { break; } e=(Element)n; } while (e!=null); //Visit them in reverse order. ListIterator it2=parents.listIterator(parents.size()-1); Element ele=null; while (it2.hasPrevious()) { ele=(Element)it2.previous(); if (set.contains(ele)) { return ele; } } return null; } }