author | mullan |
Mon, 26 Sep 2011 17:20:45 -0700 | |
changeset 10694 | cf59e2badd14 |
parent 1337 | e8d6cef36199 |
child 13791 | 059978b7e438 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
2 |
* reserved comment block |
|
3 |
* DO NOT REMOVE OR ALTER! |
|
4 |
*/ |
|
5 |
/* |
|
6 |
* Copyright 1999-2004 The Apache Software Foundation. |
|
7 |
* |
|
8 |
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
9 |
* you may not use this file except in compliance with the License. |
|
10 |
* You may obtain a copy of the License at |
|
11 |
* |
|
12 |
* http://www.apache.org/licenses/LICENSE-2.0 |
|
13 |
* |
|
14 |
* Unless required by applicable law or agreed to in writing, software |
|
15 |
* distributed under the License is distributed on an "AS IS" BASIS, |
|
16 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
17 |
* See the License for the specific language governing permissions and |
|
18 |
* limitations under the License. |
|
19 |
* |
|
20 |
*/ |
|
21 |
package com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations; |
|
22 |
||
23 |
||
24 |
||
25 |
import java.io.ByteArrayInputStream; |
|
26 |
import java.io.IOException; |
|
27 |
import java.security.PublicKey; |
|
28 |
import java.security.cert.CertificateException; |
|
29 |
import java.security.cert.CertificateFactory; |
|
30 |
import java.security.cert.X509Certificate; |
|
1337 | 31 |
import java.util.ArrayList; |
32 |
import java.util.Iterator; |
|
33 |
import java.util.List; |
|
34 |
import java.util.ListIterator; |
|
35 |
import java.util.Set; |
|
2 | 36 |
|
1337 | 37 |
import javax.xml.parsers.ParserConfigurationException; |
38 |
||
39 |
import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException; |
|
2 | 40 |
import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; |
41 |
import com.sun.org.apache.xml.internal.security.keys.content.RetrievalMethod; |
|
42 |
import com.sun.org.apache.xml.internal.security.keys.content.x509.XMLX509Certificate; |
|
43 |
import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolver; |
|
44 |
import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolverException; |
|
45 |
import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolverSpi; |
|
46 |
import com.sun.org.apache.xml.internal.security.keys.storage.StorageResolver; |
|
47 |
import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; |
|
48 |
import com.sun.org.apache.xml.internal.security.transforms.Transforms; |
|
49 |
import com.sun.org.apache.xml.internal.security.utils.Constants; |
|
50 |
import com.sun.org.apache.xml.internal.security.utils.XMLUtils; |
|
51 |
import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver; |
|
52 |
import org.w3c.dom.Attr; |
|
53 |
import org.w3c.dom.Element; |
|
54 |
import org.w3c.dom.Node; |
|
1337 | 55 |
import org.xml.sax.SAXException; |
2 | 56 |
|
57 |
||
58 |
/** |
|
59 |
* The RetrievalMethodResolver can retrieve public keys and certificates from |
|
60 |
* other locations. The location is specified using the ds:RetrievalMethod |
|
61 |
* element which points to the location. This includes the handling of raw |
|
62 |
* (binary) X.509 certificate which are not encapsulated in an XML structure. |
|
63 |
* If the retrieval process encounters an element which the |
|
64 |
* RetrievalMethodResolver cannot handle itself, resolving of the extracted |
|
65 |
* element is delegated back to the KeyResolver mechanism. |
|
66 |
* |
|
1337 | 67 |
* @author $Author: mullan $ modified by Dave Garcia |
2 | 68 |
*/ |
69 |
public class RetrievalMethodResolver extends KeyResolverSpi { |
|
70 |
||
71 |
/** {@link java.util.logging} logging facility */ |
|
72 |
static java.util.logging.Logger log = |
|
73 |
java.util.logging.Logger.getLogger( |
|
74 |
RetrievalMethodResolver.class.getName()); |
|
75 |
||
76 |
/** |
|
77 |
* Method engineResolvePublicKey |
|
78 |
* @inheritDoc |
|
79 |
* @param element |
|
80 |
* @param BaseURI |
|
81 |
* @param storage |
|
82 |
* |
|
83 |
*/ |
|
1337 | 84 |
public PublicKey engineLookupAndResolvePublicKey( |
2 | 85 |
Element element, String BaseURI, StorageResolver storage) |
86 |
{ |
|
1337 | 87 |
if (!XMLUtils.elementIsInSignatureSpace(element, |
88 |
Constants._TAG_RETRIEVALMETHOD)) { |
|
89 |
return null; |
|
90 |
} |
|
2 | 91 |
|
92 |
try { |
|
1337 | 93 |
//Create a retrieval method over the given element |
94 |
RetrievalMethod rm = new RetrievalMethod(element, BaseURI); |
|
95 |
String type = rm.getType(); |
|
96 |
XMLSignatureInput resource=resolveInput(rm,BaseURI); |
|
97 |
if (RetrievalMethod.TYPE_RAWX509.equals(type)) { |
|
98 |
//a raw certificate, direct parsing is done! |
|
99 |
X509Certificate cert=getRawCertificate(resource); |
|
100 |
if (cert != null) { |
|
101 |
return cert.getPublicKey(); |
|
102 |
} |
|
103 |
return null; |
|
104 |
}; |
|
105 |
Element e = obtainRefrenceElement(resource); |
|
106 |
return resolveKey(e,BaseURI,storage); |
|
107 |
} catch (XMLSecurityException ex) { |
|
108 |
log.log(java.util.logging.Level.FINE, "XMLSecurityException", ex); |
|
109 |
} catch (CertificateException ex) { |
|
110 |
log.log(java.util.logging.Level.FINE, "CertificateException", ex); |
|
111 |
} catch (IOException ex) { |
|
112 |
log.log(java.util.logging.Level.FINE, "IOException", ex); |
|
113 |
} catch (ParserConfigurationException e) { |
|
114 |
log.log(java.util.logging.Level.FINE, "ParserConfigurationException", e); |
|
115 |
} catch (SAXException e) { |
|
116 |
log.log(java.util.logging.Level.FINE, "SAXException", e); |
|
117 |
} |
|
118 |
return null; |
|
119 |
} |
|
2 | 120 |
|
1337 | 121 |
static private Element obtainRefrenceElement(XMLSignatureInput resource) throws CanonicalizationException, ParserConfigurationException, IOException, SAXException, KeyResolverException { |
122 |
Element e; |
|
123 |
if (resource.isElement()){ |
|
124 |
e=(Element) resource.getSubNode(); |
|
125 |
} else if (resource.isNodeSet()) { |
|
126 |
//Retrieved resource is a nodeSet |
|
127 |
e=getDocumentElement(resource.getNodeSet()); |
|
128 |
} else { |
|
129 |
//Retrieved resource is an inputStream |
|
130 |
byte inputBytes[] = resource.getBytes(); |
|
131 |
e = getDocFromBytes(inputBytes); |
|
132 |
//otherwise, we parse the resource, create an Element and delegate |
|
133 |
if (log.isLoggable(java.util.logging.Level.FINE)) |
|
134 |
log.log(java.util.logging.Level.FINE, "we have to parse " + inputBytes.length + " bytes"); |
|
135 |
} |
|
136 |
return e; |
|
2 | 137 |
} |
138 |
||
139 |
/** |
|
140 |
* Method engineResolveX509Certificate |
|
141 |
* @inheritDoc |
|
142 |
* @param element |
|
143 |
* @param BaseURI |
|
144 |
* @param storage |
|
145 |
* |
|
146 |
*/ |
|
1337 | 147 |
public X509Certificate engineLookupResolveX509Certificate( |
2 | 148 |
Element element, String BaseURI, StorageResolver storage) |
149 |
{ |
|
1337 | 150 |
if (!XMLUtils.elementIsInSignatureSpace(element, |
151 |
Constants._TAG_RETRIEVALMETHOD)) { |
|
152 |
return null; |
|
153 |
} |
|
2 | 154 |
|
1337 | 155 |
try { |
156 |
RetrievalMethod rm = new RetrievalMethod(element, BaseURI); |
|
157 |
String type = rm.getType(); |
|
158 |
XMLSignatureInput resource=resolveInput(rm,BaseURI); |
|
159 |
if (RetrievalMethod.TYPE_RAWX509.equals(type)) { |
|
160 |
X509Certificate cert=getRawCertificate(resource); |
|
161 |
return cert; |
|
162 |
} |
|
163 |
Element e = obtainRefrenceElement(resource); |
|
164 |
return resolveCertificate(e,BaseURI,storage); |
|
165 |
} catch (XMLSecurityException ex) { |
|
166 |
log.log(java.util.logging.Level.FINE, "XMLSecurityException", ex); |
|
167 |
} catch (CertificateException ex) { |
|
168 |
log.log(java.util.logging.Level.FINE, "CertificateException", ex); |
|
169 |
} catch (IOException ex) { |
|
170 |
log.log(java.util.logging.Level.FINE, "IOException", ex); |
|
171 |
} catch (ParserConfigurationException e) { |
|
172 |
log.log(java.util.logging.Level.FINE, "ParserConfigurationException", e); |
|
173 |
} catch (SAXException e) { |
|
174 |
log.log(java.util.logging.Level.FINE, "SAXException", e); |
|
175 |
} |
|
176 |
return null; |
|
177 |
} |
|
2 | 178 |
|
1337 | 179 |
/** |
180 |
* Retrieves a x509Certificate from the given information |
|
181 |
* @param e |
|
182 |
* @param BaseURI |
|
183 |
* @param storage |
|
184 |
* @return |
|
185 |
* @throws KeyResolverException |
|
186 |
*/ |
|
187 |
static private X509Certificate resolveCertificate(Element e,String BaseURI,StorageResolver storage) throws KeyResolverException{ |
|
188 |
if (log.isLoggable(java.util.logging.Level.FINE)) |
|
189 |
log.log(java.util.logging.Level.FINE, "Now we have a {" + e.getNamespaceURI() + "}"+ e.getLocalName() + " Element"); |
|
190 |
//An element has been provided |
|
191 |
if (e != null) { |
|
192 |
return KeyResolver.getX509Certificate(e,BaseURI, storage); |
|
193 |
} |
|
194 |
return null; |
|
195 |
} |
|
2 | 196 |
|
1337 | 197 |
/** |
198 |
* Retrieves a x509Certificate from the given information |
|
199 |
* @param e |
|
200 |
* @param BaseURI |
|
201 |
* @param storage |
|
202 |
* @return |
|
203 |
* @throws KeyResolverException |
|
204 |
*/ |
|
205 |
static private PublicKey resolveKey(Element e,String BaseURI,StorageResolver storage) throws KeyResolverException{ |
|
206 |
if (log.isLoggable(java.util.logging.Level.FINE)) |
|
207 |
log.log(java.util.logging.Level.FINE, "Now we have a {" + e.getNamespaceURI() + "}"+ e.getLocalName() + " Element"); |
|
208 |
//An element has been provided |
|
209 |
if (e != null) { |
|
210 |
return KeyResolver.getPublicKey(e,BaseURI, storage); |
|
2 | 211 |
} |
1337 | 212 |
return null; |
213 |
} |
|
2 | 214 |
|
1337 | 215 |
static private X509Certificate getRawCertificate(XMLSignatureInput resource) throws CanonicalizationException, IOException, CertificateException{ |
216 |
byte inputBytes[] = resource.getBytes(); |
|
217 |
// if the resource stores a raw certificate, we have to handle it |
|
218 |
CertificateFactory certFact =CertificateFactory.getInstance(XMLX509Certificate.JCA_CERT_ID); |
|
219 |
X509Certificate cert =(X509Certificate) certFact.generateCertificate(new ByteArrayInputStream(inputBytes)); |
|
220 |
return cert; |
|
221 |
} |
|
222 |
/** |
|
223 |
* Resolves the input from the given retrieval method |
|
224 |
* @return |
|
225 |
* @throws XMLSecurityException |
|
226 |
*/ |
|
227 |
static private XMLSignatureInput resolveInput(RetrievalMethod rm,String BaseURI) throws XMLSecurityException{ |
|
228 |
Attr uri = rm.getURIAttr(); |
|
229 |
//Apply the trnasforms |
|
230 |
Transforms transforms = rm.getTransforms(); |
|
231 |
ResourceResolver resRes = ResourceResolver.getInstance(uri, BaseURI); |
|
232 |
if (resRes != null) { |
|
233 |
XMLSignatureInput resource = resRes.resolve(uri, BaseURI); |
|
234 |
if (transforms != null) { |
|
235 |
log.log(java.util.logging.Level.FINE, "We have Transforms"); |
|
236 |
resource = transforms.performTransforms(resource); |
|
237 |
} |
|
238 |
return resource; |
|
239 |
} |
|
240 |
return null; |
|
2 | 241 |
} |
242 |
||
243 |
/** |
|
244 |
* Parses a byte array and returns the parsed Element. |
|
245 |
* |
|
246 |
* @param bytes |
|
247 |
* @return the Document Element after parsing bytes |
|
248 |
* @throws KeyResolverException if something goes wrong |
|
249 |
*/ |
|
1337 | 250 |
static Element getDocFromBytes(byte[] bytes) throws KeyResolverException { |
2 | 251 |
try { |
1337 | 252 |
javax.xml.parsers.DocumentBuilderFactory dbf =javax.xml.parsers.DocumentBuilderFactory.newInstance(); |
2 | 253 |
dbf.setNamespaceAware(true); |
254 |
javax.xml.parsers.DocumentBuilder db = dbf.newDocumentBuilder(); |
|
255 |
org.w3c.dom.Document doc = |
|
256 |
db.parse(new java.io.ByteArrayInputStream(bytes)); |
|
257 |
return doc.getDocumentElement(); |
|
258 |
} catch (org.xml.sax.SAXException ex) { |
|
259 |
throw new KeyResolverException("empty", ex); |
|
260 |
} catch (java.io.IOException ex) { |
|
261 |
throw new KeyResolverException("empty", ex); |
|
262 |
} catch (javax.xml.parsers.ParserConfigurationException ex) { |
|
263 |
throw new KeyResolverException("empty", ex); |
|
264 |
} |
|
265 |
} |
|
266 |
||
267 |
/** |
|
268 |
* Method engineResolveSecretKey |
|
269 |
* @inheritDoc |
|
270 |
* @param element |
|
271 |
* @param BaseURI |
|
272 |
* @param storage |
|
273 |
* |
|
274 |
*/ |
|
1337 | 275 |
public javax.crypto.SecretKey engineLookupAndResolveSecretKey( |
2 | 276 |
Element element, String BaseURI, StorageResolver storage) |
277 |
{ |
|
278 |
return null; |
|
279 |
} |
|
1337 | 280 |
|
10694
cf59e2badd14
7088502: Security libraries don't build with javac -Werror
mullan
parents:
1337
diff
changeset
|
281 |
static Element getDocumentElement(Set<Node> set) { |
cf59e2badd14
7088502: Security libraries don't build with javac -Werror
mullan
parents:
1337
diff
changeset
|
282 |
Iterator<Node> it=set.iterator(); |
1337 | 283 |
Element e=null; |
284 |
while (it.hasNext()) { |
|
10694
cf59e2badd14
7088502: Security libraries don't build with javac -Werror
mullan
parents:
1337
diff
changeset
|
285 |
Node currentNode=it.next(); |
1337 | 286 |
if (currentNode instanceof Element) { |
287 |
e=(Element)currentNode; |
|
288 |
break; |
|
289 |
} |
|
290 |
||
291 |
} |
|
10694
cf59e2badd14
7088502: Security libraries don't build with javac -Werror
mullan
parents:
1337
diff
changeset
|
292 |
List<Element> parents=new ArrayList<Element>(10); |
1337 | 293 |
|
294 |
//Obtain all the parents of the elemnt |
|
295 |
do { |
|
296 |
parents.add(e); |
|
297 |
Node n=e.getParentNode(); |
|
298 |
if (!(n instanceof Element )) { |
|
299 |
break; |
|
300 |
} |
|
301 |
e=(Element)n; |
|
302 |
} while (e!=null); |
|
303 |
//Visit them in reverse order. |
|
10694
cf59e2badd14
7088502: Security libraries don't build with javac -Werror
mullan
parents:
1337
diff
changeset
|
304 |
ListIterator<Element> it2=parents.listIterator(parents.size()-1); |
1337 | 305 |
Element ele=null; |
306 |
while (it2.hasPrevious()) { |
|
10694
cf59e2badd14
7088502: Security libraries don't build with javac -Werror
mullan
parents:
1337
diff
changeset
|
307 |
ele=it2.previous(); |
1337 | 308 |
if (set.contains(ele)) { |
309 |
return ele; |
|
310 |
} |
|
311 |
} |
|
312 |
return null; |
|
2 | 313 |
} |
314 |
} |