| 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
package com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations;  | 
 | 
 | 
 | 
import java.io.ByteArrayInputStream;  | 
 | 
import java.io.IOException;  | 
 | 
import java.io.InputStream;  | 
 | 
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;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
public class RetrievalMethodResolver extends KeyResolverSpi { | 
 | 
 | 
 | 
    private static final com.sun.org.slf4j.internal.Logger LOG =  | 
 | 
        com.sun.org.slf4j.internal.LoggerFactory.getLogger(RetrievalMethodResolver.class);  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public PublicKey engineLookupAndResolvePublicKey(  | 
 | 
           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, secureValidation);  | 
 | 
            if (RetrievalMethod.TYPE_RAWX509.equals(type)) { | 
 | 
                  | 
 | 
                X509Certificate cert = getRawCertificate(resource);  | 
 | 
                if (cert != null) { | 
 | 
                    return cert.getPublicKey();  | 
 | 
                }  | 
 | 
                return null;  | 
 | 
             }  | 
 | 
             Element e = obtainReferenceElement(resource, secureValidation);  | 
 | 
 | 
 | 
             // Check to make sure that the reference is not to another RetrievalMethod  | 
 | 
               | 
 | 
             if (XMLUtils.elementIsInSignatureSpace(e, Constants._TAG_RETRIEVALMETHOD)) { | 
 | 
                 if (secureValidation) { | 
 | 
                     if (LOG.isDebugEnabled()) { | 
 | 
                         String error = "Error: It is forbidden to have one RetrievalMethod "  | 
 | 
                             + "point to another with secure validation";  | 
 | 
                         LOG.debug(error);  | 
 | 
                     }  | 
 | 
                     return null;  | 
 | 
                 }  | 
 | 
                 RetrievalMethod rm2 = new RetrievalMethod(e, baseURI);  | 
 | 
                 XMLSignatureInput resource2 = resolveInput(rm2, baseURI, secureValidation);  | 
 | 
                 Element e2 = obtainReferenceElement(resource2, secureValidation);  | 
 | 
                 if (e2 == element) { | 
 | 
                     LOG.debug("Error: Can't have RetrievalMethods pointing to each other"); | 
 | 
                     return null;  | 
 | 
                 }  | 
 | 
             }  | 
 | 
 | 
 | 
             return resolveKey(e, baseURI, storage);  | 
 | 
         } catch (XMLSecurityException ex) { | 
 | 
             LOG.debug("XMLSecurityException", ex); | 
 | 
         } catch (CertificateException ex) { | 
 | 
             LOG.debug("CertificateException", ex); | 
 | 
         } catch (IOException ex) { | 
 | 
             LOG.debug("IOException", ex); | 
 | 
         } catch (ParserConfigurationException e) { | 
 | 
             LOG.debug("ParserConfigurationException", e); | 
 | 
         } catch (SAXException e) { | 
 | 
             LOG.debug("SAXException", e); | 
 | 
         }  | 
 | 
         return null;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    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, secureValidation);  | 
 | 
            if (RetrievalMethod.TYPE_RAWX509.equals(type)) { | 
 | 
                return getRawCertificate(resource);  | 
 | 
            }  | 
 | 
 | 
 | 
            Element e = obtainReferenceElement(resource, secureValidation);  | 
 | 
 | 
 | 
            // Check to make sure that the reference is not to another RetrievalMethod  | 
 | 
              | 
 | 
            if (XMLUtils.elementIsInSignatureSpace(e, Constants._TAG_RETRIEVALMETHOD)) { | 
 | 
                if (secureValidation) { | 
 | 
                    if (LOG.isDebugEnabled()) { | 
 | 
                        String error = "Error: It is forbidden to have one RetrievalMethod "  | 
 | 
                            + "point to another with secure validation";  | 
 | 
                        LOG.debug(error);  | 
 | 
                    }  | 
 | 
                    return null;  | 
 | 
                }  | 
 | 
                RetrievalMethod rm2 = new RetrievalMethod(e, baseURI);  | 
 | 
                XMLSignatureInput resource2 = resolveInput(rm2, baseURI, secureValidation);  | 
 | 
                Element e2 = obtainReferenceElement(resource2, secureValidation);  | 
 | 
                if (e2 == element) { | 
 | 
                    LOG.debug("Error: Can't have RetrievalMethods pointing to each other"); | 
 | 
                    return null;  | 
 | 
                }  | 
 | 
            }  | 
 | 
 | 
 | 
            return resolveCertificate(e, baseURI, storage);  | 
 | 
        } catch (XMLSecurityException ex) { | 
 | 
            LOG.debug("XMLSecurityException", ex); | 
 | 
        } catch (CertificateException ex) { | 
 | 
            LOG.debug("CertificateException", ex); | 
 | 
        } catch (IOException ex) { | 
 | 
            LOG.debug("IOException", ex); | 
 | 
        } catch (ParserConfigurationException e) { | 
 | 
            LOG.debug("ParserConfigurationException", e); | 
 | 
        } catch (SAXException e) { | 
 | 
            LOG.debug("SAXException", e); | 
 | 
        }  | 
 | 
        return null;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static X509Certificate resolveCertificate(  | 
 | 
        Element e, String baseURI, StorageResolver storage  | 
 | 
    ) throws KeyResolverException { | 
 | 
        if (LOG.isDebugEnabled()) { | 
 | 
            LOG.debug("Now we have a {" + e.getNamespaceURI() + "}" | 
 | 
                + e.getLocalName() + " Element");  | 
 | 
        }  | 
 | 
          | 
 | 
        if (e != null) { | 
 | 
            return KeyResolver.getX509Certificate(e, baseURI, storage);  | 
 | 
        }  | 
 | 
        return null;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static PublicKey resolveKey(  | 
 | 
        Element e, String baseURI, StorageResolver storage  | 
 | 
    ) throws KeyResolverException { | 
 | 
        if (LOG.isDebugEnabled()) { | 
 | 
            LOG.debug("Now we have a {" + e.getNamespaceURI() + "}" | 
 | 
                + e.getLocalName() + " Element");  | 
 | 
        }  | 
 | 
          | 
 | 
        if (e != null) { | 
 | 
            return KeyResolver.getPublicKey(e, baseURI, storage);  | 
 | 
        }  | 
 | 
        return null;  | 
 | 
    }  | 
 | 
 | 
 | 
    private static Element obtainReferenceElement(XMLSignatureInput resource, boolean secureValidation)  | 
 | 
        throws CanonicalizationException, ParserConfigurationException,  | 
 | 
        IOException, SAXException, KeyResolverException { | 
 | 
        Element e;  | 
 | 
        if (resource.isElement()){ | 
 | 
            e = (Element) resource.getSubNode();  | 
 | 
        } else if (resource.isNodeSet()) { | 
 | 
              | 
 | 
            e = getDocumentElement(resource.getNodeSet());  | 
 | 
        } else { | 
 | 
              | 
 | 
            byte inputBytes[] = resource.getBytes();  | 
 | 
            e = getDocFromBytes(inputBytes, secureValidation);  | 
 | 
              | 
 | 
            LOG.debug("we have to parse {} bytes", inputBytes.length); | 
 | 
        }  | 
 | 
        return e;  | 
 | 
    }  | 
 | 
 | 
 | 
    private static X509Certificate getRawCertificate(XMLSignatureInput resource)  | 
 | 
        throws CanonicalizationException, IOException, CertificateException { | 
 | 
        byte inputBytes[] = resource.getBytes();  | 
 | 
          | 
 | 
        CertificateFactory certFact =  | 
 | 
            CertificateFactory.getInstance(XMLX509Certificate.JCA_CERT_ID);  | 
 | 
        try (InputStream is = new ByteArrayInputStream(inputBytes)) { | 
 | 
            return (X509Certificate) certFact.generateCertificate(is);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static XMLSignatureInput resolveInput(  | 
 | 
        RetrievalMethod rm, String baseURI, boolean secureValidation  | 
 | 
    ) throws XMLSecurityException { | 
 | 
        Attr uri = rm.getURIAttr();  | 
 | 
          | 
 | 
        Transforms transforms = rm.getTransforms();  | 
 | 
        ResourceResolver resRes = ResourceResolver.getInstance(uri, baseURI, secureValidation);  | 
 | 
        XMLSignatureInput resource = resRes.resolve(uri, baseURI, secureValidation);  | 
 | 
        if (transforms != null) { | 
 | 
            LOG.debug("We have Transforms"); | 
 | 
            resource = transforms.performTransforms(resource);  | 
 | 
        }  | 
 | 
        return resource;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public javax.crypto.SecretKey engineLookupAndResolveSecretKey(  | 
 | 
        Element element, String baseURI, StorageResolver storage  | 
 | 
    ) { | 
 | 
        return null;  | 
 | 
    }  | 
 | 
 | 
 | 
    private static Element getDocumentElement(Set<Node> set) { | 
 | 
        Iterator<Node> it = set.iterator();  | 
 | 
        Element e = null;  | 
 | 
        while (it.hasNext()) { | 
 | 
            Node currentNode = it.next();  | 
 | 
            if (currentNode != null && Node.ELEMENT_NODE == currentNode.getNodeType()) { | 
 | 
                e = (Element) currentNode;  | 
 | 
                break;  | 
 | 
            }  | 
 | 
        }  | 
 | 
        List<Node> parents = new ArrayList<>();  | 
 | 
 | 
 | 
          | 
 | 
        while (e != null) { | 
 | 
            parents.add(e);  | 
 | 
            Node n = e.getParentNode();  | 
 | 
            if (n == null || Node.ELEMENT_NODE != n.getNodeType()) { | 
 | 
                break;  | 
 | 
            }  | 
 | 
            e = (Element) n;  | 
 | 
        }  | 
 | 
          | 
 | 
        ListIterator<Node> it2 = parents.listIterator(parents.size()-1);  | 
 | 
        Element ele = null;  | 
 | 
        while (it2.hasPrevious()) { | 
 | 
            ele = (Element) it2.previous();  | 
 | 
            if (set.contains(ele)) { | 
 | 
                return ele;  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return null;  | 
 | 
    }  | 
 | 
}  |