blob: d8d98bdb9e9651f47049990b377e4a6f7267c344 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
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 */
21package com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations;
22
23
24
25import java.io.ByteArrayInputStream;
26import java.io.IOException;
27import java.security.PublicKey;
28import java.security.cert.CertificateException;
29import java.security.cert.CertificateFactory;
30import java.security.cert.X509Certificate;
31
32import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
33import com.sun.org.apache.xml.internal.security.keys.content.RetrievalMethod;
34import com.sun.org.apache.xml.internal.security.keys.content.x509.XMLX509Certificate;
35import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolver;
36import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolverException;
37import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolverSpi;
38import com.sun.org.apache.xml.internal.security.keys.storage.StorageResolver;
39import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;
40import com.sun.org.apache.xml.internal.security.transforms.Transforms;
41import com.sun.org.apache.xml.internal.security.utils.Constants;
42import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
43import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolver;
44import org.w3c.dom.Attr;
45import org.w3c.dom.Element;
46import org.w3c.dom.Node;
47
48
49/**
50 * The RetrievalMethodResolver can retrieve public keys and certificates from
51 * other locations. The location is specified using the ds:RetrievalMethod
52 * element which points to the location. This includes the handling of raw
53 * (binary) X.509 certificate which are not encapsulated in an XML structure.
54 * If the retrieval process encounters an element which the
55 * RetrievalMethodResolver cannot handle itself, resolving of the extracted
56 * element is delegated back to the KeyResolver mechanism.
57 *
58 * @author $Author: raul $
59 */
60public class RetrievalMethodResolver extends KeyResolverSpi {
61
62 /** {@link java.util.logging} logging facility */
63 static java.util.logging.Logger log =
64 java.util.logging.Logger.getLogger(
65 RetrievalMethodResolver.class.getName());
66
67 /**
68 * Method engineCanResolve
69 * @inheritDoc
70 * @param element
71 * @param BaseURI
72 * @param storage
73 *
74 */
75 public boolean engineCanResolve(Element element, String BaseURI,
76 StorageResolver storage) {
77
78 if
79 (!XMLUtils.elementIsInSignatureSpace(element,
80 Constants._TAG_RETRIEVALMETHOD)) {
81 return false;
82 }
83
84 return true;
85 }
86
87 /**
88 * Method engineResolvePublicKey
89 * @inheritDoc
90 * @param element
91 * @param BaseURI
92 * @param storage
93 *
94 */
95 public PublicKey engineResolvePublicKey(
96 Element element, String BaseURI, StorageResolver storage)
97 {
98
99 try {
100 RetrievalMethod rm = new RetrievalMethod(element, BaseURI);
101 Attr uri = rm.getURIAttr();
102
103 // type can be null because it's optional
104 String type = rm.getType();
105 Transforms transforms = rm.getTransforms();
106 ResourceResolver resRes = ResourceResolver.getInstance(uri, BaseURI);
107
108 if (resRes != null) {
109 XMLSignatureInput resource = resRes.resolve(uri, BaseURI);
110 if (true)
111 if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Before applying Transforms, resource has "
112 + resource.getBytes().length + "bytes");
113
114 if (transforms != null) {
115 if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "We have Transforms");
116
117 resource = transforms.performTransforms(resource);
118 }
119 if (true) {
120 if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "After applying Transforms, resource has "
121 + resource.getBytes().length + "bytes");
122 if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Resolved to resource " + resource.getSourceURI());
123 }
124
125 byte inputBytes[] = resource.getBytes();
126
127 if ((type != null) && type.equals(RetrievalMethod.TYPE_RAWX509)) {
128
129 // if the resource stores a raw certificate, we have to handle it
130 CertificateFactory certFact =
131 CertificateFactory
132 .getInstance(XMLX509Certificate.JCA_CERT_ID);
133 X509Certificate cert =
134 (X509Certificate) certFact
135 .generateCertificate(new ByteArrayInputStream(inputBytes));
136
137 if (cert != null) {
138 return cert.getPublicKey();
139 }
140 } else {
141
142 // otherwise, we parse the resource, create an Element and delegate
143 if (true)
144 if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "we have to parse " + inputBytes.length + " bytes");
145
146 Element e = this.getDocFromBytes(inputBytes);
147 if (true)
148 if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Now we have a {" + e.getNamespaceURI() + "}"
149 + e.getLocalName() + " Element");
150
151 if (e != null) {
152 KeyResolver newKeyResolver = KeyResolver.getInstance(getFirstElementChild(e),
153 BaseURI, storage);
154
155 if (newKeyResolver != null) {
156 return newKeyResolver.resolvePublicKey(getFirstElementChild(e), BaseURI,
157 storage);
158 }
159 }
160 }
161 }
162 } catch (XMLSecurityException ex) {
163 if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "XMLSecurityException", ex);
164 } catch (CertificateException ex) {
165 if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "CertificateException", ex);
166 } catch (IOException ex) {
167 if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "IOException", ex);
168 }
169
170 return null;
171 }
172
173 /**
174 * Method engineResolveX509Certificate
175 * @inheritDoc
176 * @param element
177 * @param BaseURI
178 * @param storage
179 *
180 */
181 public X509Certificate engineResolveX509Certificate(
182 Element element, String BaseURI, StorageResolver storage)
183 {
184
185 try {
186 RetrievalMethod rm = new RetrievalMethod(element, BaseURI);
187 Attr uri = rm.getURIAttr();
188 Transforms transforms = rm.getTransforms();
189 if (true)
190 if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Asked to resolve URI " + uri);
191
192 ResourceResolver resRes = ResourceResolver.getInstance(uri, BaseURI);
193
194 if (resRes != null) {
195 XMLSignatureInput resource = resRes.resolve(uri, BaseURI);
196 if (true)
197 if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Before applying Transforms, resource has "
198 + resource.getBytes().length + "bytes");
199
200 if (transforms != null) {
201 if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "We have Transforms");
202
203 resource = transforms.performTransforms(resource);
204 }
205
206 if (true) {
207 if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "After applying Transforms, resource has "
208 + resource.getBytes().length + "bytes");
209 if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Resolved to resource " + resource.getSourceURI());
210 }
211
212 byte inputBytes[] = resource.getBytes();
213
214 if ((rm.getType() != null)
215 && rm.getType().equals(RetrievalMethod.TYPE_RAWX509)) {
216
217 // if the resource stores a raw certificate, we have to handle it
218 CertificateFactory certFact =
219 CertificateFactory
220 .getInstance(XMLX509Certificate.JCA_CERT_ID);
221 X509Certificate cert =
222 (X509Certificate) certFact
223 .generateCertificate(new ByteArrayInputStream(inputBytes));
224
225 if (cert != null) {
226 return cert;
227 }
228 } else {
229
230 // otherwise, we parse the resource, create an Element and delegate
231 if (true)
232 if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "we have to parse " + inputBytes.length + " bytes");
233
234 Element e = this.getDocFromBytes(inputBytes);
235
236 if (true)
237 if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Now we have a {" + e.getNamespaceURI() + "}"
238 + e.getLocalName() + " Element");
239
240 if (e != null) {
241 KeyResolver newKeyResolver = KeyResolver.getInstance(getFirstElementChild(e),
242 BaseURI, storage);
243
244 if (newKeyResolver != null) {
245 return newKeyResolver.resolveX509Certificate(getFirstElementChild(e), BaseURI,
246 storage);
247 }
248 }
249 }
250 }
251 } catch (XMLSecurityException ex) {
252 if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "XMLSecurityException", ex);
253 } catch (CertificateException ex) {
254 if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "CertificateException", ex);
255 } catch (IOException ex) {
256 if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "IOException", ex);
257 }
258
259 return null;
260 }
261
262 /**
263 * Parses a byte array and returns the parsed Element.
264 *
265 * @param bytes
266 * @return the Document Element after parsing bytes
267 * @throws KeyResolverException if something goes wrong
268 */
269 Element getDocFromBytes(byte[] bytes) throws KeyResolverException {
270
271 try {
272 javax.xml.parsers.DocumentBuilderFactory dbf =
273 javax.xml.parsers.DocumentBuilderFactory.newInstance();
274
275 dbf.setNamespaceAware(true);
276
277 javax.xml.parsers.DocumentBuilder db = dbf.newDocumentBuilder();
278 org.w3c.dom.Document doc =
279 db.parse(new java.io.ByteArrayInputStream(bytes));
280
281 return doc.getDocumentElement();
282 } catch (org.xml.sax.SAXException ex) {
283 throw new KeyResolverException("empty", ex);
284 } catch (java.io.IOException ex) {
285 throw new KeyResolverException("empty", ex);
286 } catch (javax.xml.parsers.ParserConfigurationException ex) {
287 throw new KeyResolverException("empty", ex);
288 }
289 }
290
291 /**
292 * Method engineResolveSecretKey
293 * @inheritDoc
294 * @param element
295 * @param BaseURI
296 * @param storage
297 *
298 */
299 public javax.crypto.SecretKey engineResolveSecretKey(
300 Element element, String BaseURI, StorageResolver storage)
301 {
302 return null;
303 }
304 static Element getFirstElementChild(Element e){
305 Node n=e.getFirstChild();
306 while (n!=null && n.getNodeType()!=Node.ELEMENT_NODE) {
307 n=n.getNextSibling();
308 }
309 return (Element)n;
310 }
311}