1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /**
   6  * Licensed to the Apache Software Foundation (ASF) under one
   7  * or more contributor license agreements. See the NOTICE file
   8  * distributed with this work for additional information
   9  * regarding copyright ownership. The ASF licenses this file
  10  * to you under the Apache License, Version 2.0 (the
  11  * "License"); you may not use this file except in compliance
  12  * with the License. You may obtain a copy of the License at
  13  *
  14  * http://www.apache.org/licenses/LICENSE-2.0
  15  *
  16  * Unless required by applicable law or agreed to in writing,
  17  * software distributed under the License is distributed on an
  18  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  19  * KIND, either express or implied. See the License for the
  20  * specific language governing permissions and limitations
  21  * under the License.
  22  */
  23 /*
  24  * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
  25  */
  26 /*
  27  * $Id: DOMURIDereferencer.java 1231033 2012-01-13 12:12:12Z coheigea $
  28  */
  29 package org.jcp.xml.dsig.internal.dom;
  30 
  31 import org.w3c.dom.Attr;
  32 import org.w3c.dom.Element;
  33 import org.w3c.dom.Node;
  34 
  35 import com.sun.org.apache.xml.internal.security.Init;
  36 import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
  37 import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver;
  38 import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;
  39 
  40 import javax.xml.crypto.*;
  41 import javax.xml.crypto.dom.*;
  42 
  43 /**
  44  * DOM-based implementation of URIDereferencer.
  45  *
  46  * @author Sean Mullan
  47  */
  48 public class DOMURIDereferencer implements URIDereferencer {
  49 
  50     static final URIDereferencer INSTANCE = new DOMURIDereferencer();
  51 
  52     private DOMURIDereferencer() {
  53         // need to call com.sun.org.apache.xml.internal.security.Init.init()
  54         // before calling any apache security code
  55         Init.init();
  56     }
  57 
  58     public Data dereference(URIReference uriRef, XMLCryptoContext context)
  59         throws URIReferenceException {
  60 
  61         if (uriRef == null) {
  62             throw new NullPointerException("uriRef cannot be null");
  63         }
  64         if (context == null) {
  65             throw new NullPointerException("context cannot be null");
  66         }
  67 
  68         DOMURIReference domRef = (DOMURIReference) uriRef;
  69         Attr uriAttr = (Attr) domRef.getHere();
  70         String uri = uriRef.getURI();
  71         DOMCryptoContext dcc = (DOMCryptoContext) context;
  72         String baseURI = context.getBaseURI();
  73 
  74         boolean secVal = Utils.secureValidation(context);
  75 
  76         // Check if same-document URI and already registered on the context
  77         if (uri != null && uri.length() != 0 && uri.charAt(0) == '#') {
  78             String id = uri.substring(1);
  79 
  80             if (id.startsWith("xpointer(id(")) {
  81                 int i1 = id.indexOf('\'');
  82                 int i2 = id.indexOf('\'', i1+1);
  83                 id = id.substring(i1+1, i2);
  84             }
  85 
  86             Node referencedElem = dcc.getElementById(id);
  87             if (referencedElem != null) {
  88                 if (secVal) {
  89                     Element start = referencedElem.getOwnerDocument().getDocumentElement();
  90                     if (!XMLUtils.protectAgainstWrappingAttack(start, (Element)referencedElem, id)) {
  91                         String error = "Multiple Elements with the same ID " + id + " were detected";
  92                         throw new URIReferenceException(error);
  93                     }
  94                 }
  95 
  96                 XMLSignatureInput result = new XMLSignatureInput(referencedElem);
  97                 if (!uri.substring(1).startsWith("xpointer(id(")) {
  98                     result.setExcludeComments(true);
  99                 }
 100 
 101                 result.setMIMEType("text/xml");
 102                 if (baseURI != null && baseURI.length() > 0) {
 103                     result.setSourceURI(baseURI.concat(uriAttr.getNodeValue()));
 104                 } else {
 105                     result.setSourceURI(uriAttr.getNodeValue());
 106                 }
 107                 return new ApacheNodeSetData(result);
 108             }
 109         }
 110 
 111         try {
 112             ResourceResolver apacheResolver =
 113                 ResourceResolver.getInstance(uriAttr, baseURI, secVal);
 114             XMLSignatureInput in = apacheResolver.resolve(uriAttr, baseURI);
 115             if (in.isOctetStream()) {
 116                 return new ApacheOctetStreamData(in);
 117             } else {
 118                 return new ApacheNodeSetData(in);
 119             }
 120         } catch (Exception e) {
 121             throw new URIReferenceException(e);
 122         }
 123     }
 124 }