J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * reserved comment block |
| 3 | * DO NOT REMOVE OR ALTER! |
| 4 | */ |
| 5 | |
| 6 | /* |
| 7 | * Copyright 1999-2004 The Apache Software Foundation. |
| 8 | * |
| 9 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 10 | * you may not use this file except in compliance with the License. |
| 11 | * You may obtain a copy of the License at |
| 12 | * |
| 13 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 14 | * |
| 15 | * Unless required by applicable law or agreed to in writing, software |
| 16 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 18 | * See the License for the specific language governing permissions and |
| 19 | * limitations under the License. |
| 20 | * |
| 21 | */ |
| 22 | package com.sun.org.apache.xml.internal.security.utils.resolver.implementations; |
| 23 | |
| 24 | import java.io.ByteArrayOutputStream; |
| 25 | import java.io.IOException; |
| 26 | import java.io.InputStream; |
| 27 | import java.net.MalformedURLException; |
| 28 | import java.net.URL; |
| 29 | import java.net.URLConnection; |
| 30 | |
| 31 | import com.sun.org.apache.xml.internal.utils.URI; |
| 32 | import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; |
| 33 | import com.sun.org.apache.xml.internal.security.utils.Base64; |
| 34 | import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException; |
| 35 | import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverSpi; |
| 36 | import org.w3c.dom.Attr; |
| 37 | |
| 38 | |
| 39 | /** |
| 40 | * A simple ResourceResolver for HTTP requests. This class handles only 'pure' |
| 41 | * HTTP URIs which means without a fragment. The Fragment handling is done by the |
| 42 | * {@link ResolverFragment} class. |
| 43 | * <BR> |
| 44 | * If the user has a corporate HTTP proxy which is to be used, the usage can be |
| 45 | * switched on by setting properties for the resolver: |
| 46 | * <PRE> |
| 47 | * resourceResolver.setProperty("http.proxy.host", "proxy.company.com"); |
| 48 | * resourceResolver.setProperty("http.proxy.port", "8080"); |
| 49 | * |
| 50 | * // if we need a password for the proxy |
| 51 | * resourceResolver.setProperty("http.proxy.username", "proxyuser3"); |
| 52 | * resourceResolver.setProperty("http.proxy.password", "secretca"); |
| 53 | * </PRE> |
| 54 | * |
| 55 | * |
| 56 | * @author $Author: mullan $ |
| 57 | * @see <A HREF="http://www.javaworld.com/javaworld/javatips/jw-javatip42_p.html">Java Tip 42: Write Java apps that work with proxy-based firewalls</A> |
| 58 | * @see <A HREF="http://java.sun.com/j2se/1.4/docs/guide/net/properties.html">SUN J2SE docs for network properties</A> |
| 59 | * @see <A HREF="http://metalab.unc.edu/javafaq/javafaq.html#proxy">The JAVA FAQ Question 9.5: How do I make Java work with a proxy server?</A> |
| 60 | * $todo$ the proxy behaviour seems not to work; if a on-existing proxy is set, it works ?!? |
| 61 | */ |
| 62 | public class ResolverDirectHTTP extends ResourceResolverSpi { |
| 63 | |
| 64 | /** {@link java.util.logging} logging facility */ |
| 65 | static java.util.logging.Logger log = |
| 66 | java.util.logging.Logger.getLogger( |
| 67 | ResolverDirectHTTP.class.getName()); |
| 68 | |
| 69 | /** Field properties[] */ |
| 70 | static final String properties[] = { "http.proxy.host", "http.proxy.port", |
| 71 | "http.proxy.username", |
| 72 | "http.proxy.password", |
| 73 | "http.basic.username", |
| 74 | "http.basic.password" }; |
| 75 | |
| 76 | /** Field HttpProxyHost */ |
| 77 | private static final int HttpProxyHost = 0; |
| 78 | |
| 79 | /** Field HttpProxyPort */ |
| 80 | private static final int HttpProxyPort = 1; |
| 81 | |
| 82 | /** Field HttpProxyUser */ |
| 83 | private static final int HttpProxyUser = 2; |
| 84 | |
| 85 | /** Field HttpProxyPass */ |
| 86 | private static final int HttpProxyPass = 3; |
| 87 | |
| 88 | /** Field HttpProxyUser */ |
| 89 | private static final int HttpBasicUser = 4; |
| 90 | |
| 91 | /** Field HttpProxyPass */ |
| 92 | private static final int HttpBasicPass = 5; |
| 93 | |
| 94 | /** |
| 95 | * Method resolve |
| 96 | * |
| 97 | * @param uri |
| 98 | * @param BaseURI |
| 99 | * |
| 100 | * @throws ResourceResolverException |
| 101 | * @return |
| 102 | * $todo$ calculate the correct URI from the attribute and the BaseURI |
| 103 | */ |
| 104 | public XMLSignatureInput engineResolve(Attr uri, String BaseURI) |
| 105 | throws ResourceResolverException { |
| 106 | |
| 107 | try { |
| 108 | boolean useProxy = false; |
| 109 | String proxyHost = |
| 110 | engineGetProperty(ResolverDirectHTTP |
| 111 | .properties[ResolverDirectHTTP.HttpProxyHost]); |
| 112 | String proxyPort = |
| 113 | engineGetProperty(ResolverDirectHTTP |
| 114 | .properties[ResolverDirectHTTP.HttpProxyPort]); |
| 115 | |
| 116 | if ((proxyHost != null) && (proxyPort != null)) { |
| 117 | useProxy = true; |
| 118 | } |
| 119 | |
| 120 | // switch on proxy usage |
| 121 | String oldProxySet = null; |
| 122 | String oldProxyHost = null; |
| 123 | String oldProxyPort = null; |
| 124 | if (useProxy) { |
| 125 | if (log.isLoggable(java.util.logging.Level.FINE)) { |
| 126 | log.log(java.util.logging.Level.FINE, |
| 127 | "Use of HTTP proxy enabled: " + proxyHost + ":" |
| 128 | + proxyPort); |
| 129 | } |
| 130 | oldProxySet = System.getProperty("http.proxySet"); |
| 131 | oldProxyHost = System.getProperty("http.proxyHost"); |
| 132 | oldProxyPort = System.getProperty("http.proxyPort"); |
| 133 | System.setProperty("http.proxySet", "true"); |
| 134 | System.setProperty("http.proxyHost", proxyHost); |
| 135 | System.setProperty("http.proxyPort", proxyPort); |
| 136 | } |
| 137 | |
| 138 | boolean switchBackProxy = ((oldProxySet != null) |
| 139 | && (oldProxyHost != null) |
| 140 | && (oldProxyPort != null)); |
| 141 | |
| 142 | // calculate new URI |
| 143 | URI uriNew = getNewURI(uri.getNodeValue(), BaseURI); |
| 144 | |
| 145 | // if the URI contains a fragment, ignore it |
| 146 | URI uriNewNoFrag = new URI(uriNew); |
| 147 | |
| 148 | uriNewNoFrag.setFragment(null); |
| 149 | |
| 150 | URL url = new URL(uriNewNoFrag.toString()); |
| 151 | URLConnection urlConnection = url.openConnection(); |
| 152 | |
| 153 | { |
| 154 | |
| 155 | // set proxy pass |
| 156 | String proxyUser = |
| 157 | engineGetProperty(ResolverDirectHTTP |
| 158 | .properties[ResolverDirectHTTP.HttpProxyUser]); |
| 159 | String proxyPass = |
| 160 | engineGetProperty(ResolverDirectHTTP |
| 161 | .properties[ResolverDirectHTTP.HttpProxyPass]); |
| 162 | |
| 163 | if ((proxyUser != null) && (proxyPass != null)) { |
| 164 | String password = proxyUser + ":" + proxyPass; |
| 165 | String encodedPassword = Base64.encode(password.getBytes()); |
| 166 | |
| 167 | // or was it Proxy-Authenticate ? |
| 168 | urlConnection.setRequestProperty("Proxy-Authorization", |
| 169 | encodedPassword); |
| 170 | } |
| 171 | } |
| 172 | |
| 173 | { |
| 174 | |
| 175 | // check if Basic authentication is required |
| 176 | String auth = urlConnection.getHeaderField("WWW-Authenticate"); |
| 177 | |
| 178 | if (auth != null) { |
| 179 | |
| 180 | // do http basic authentication |
| 181 | if (auth.startsWith("Basic")) { |
| 182 | String user = |
| 183 | engineGetProperty(ResolverDirectHTTP |
| 184 | .properties[ResolverDirectHTTP.HttpBasicUser]); |
| 185 | String pass = |
| 186 | engineGetProperty(ResolverDirectHTTP |
| 187 | .properties[ResolverDirectHTTP.HttpBasicPass]); |
| 188 | |
| 189 | if ((user != null) && (pass != null)) { |
| 190 | urlConnection = url.openConnection(); |
| 191 | |
| 192 | String password = user + ":" + pass; |
| 193 | String encodedPassword = |
| 194 | Base64.encode(password.getBytes()); |
| 195 | |
| 196 | // set authentication property in the http header |
| 197 | urlConnection.setRequestProperty("Authorization", |
| 198 | "Basic " |
| 199 | + encodedPassword); |
| 200 | } |
| 201 | } |
| 202 | } |
| 203 | } |
| 204 | |
| 205 | String mimeType = urlConnection.getHeaderField("Content-Type"); |
| 206 | InputStream inputStream = urlConnection.getInputStream(); |
| 207 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| 208 | byte buf[] = new byte[4096]; |
| 209 | int read = 0; |
| 210 | int summarized = 0; |
| 211 | |
| 212 | while ((read = inputStream.read(buf)) >= 0) { |
| 213 | baos.write(buf, 0, read); |
| 214 | |
| 215 | summarized += read; |
| 216 | } |
| 217 | |
| 218 | if (log.isLoggable(java.util.logging.Level.FINE)) { |
| 219 | log.log(java.util.logging.Level.FINE, |
| 220 | "Fetched " + summarized + " bytes from URI " |
| 221 | + uriNew.toString()); |
| 222 | } |
| 223 | |
| 224 | XMLSignatureInput result = new XMLSignatureInput(baos.toByteArray()); |
| 225 | |
| 226 | // XMLSignatureInput result = new XMLSignatureInput(inputStream); |
| 227 | result.setSourceURI(uriNew.toString()); |
| 228 | result.setMIMEType(mimeType); |
| 229 | |
| 230 | // switch off proxy usage |
| 231 | if (useProxy && switchBackProxy) { |
| 232 | System.setProperty("http.proxySet", oldProxySet); |
| 233 | System.setProperty("http.proxyHost", oldProxyHost); |
| 234 | System.setProperty("http.proxyPort", oldProxyPort); |
| 235 | } |
| 236 | |
| 237 | return result; |
| 238 | } catch (MalformedURLException ex) { |
| 239 | throw new ResourceResolverException("generic.EmptyMessage", ex, uri, |
| 240 | BaseURI); |
| 241 | } catch (IOException ex) { |
| 242 | throw new ResourceResolverException("generic.EmptyMessage", ex, uri, |
| 243 | BaseURI); |
| 244 | } |
| 245 | } |
| 246 | |
| 247 | /** |
| 248 | * We resolve http URIs <I>without</I> fragment... |
| 249 | * |
| 250 | * @param uri |
| 251 | * @param BaseURI |
| 252 | * @return true if can be resolved |
| 253 | */ |
| 254 | public boolean engineCanResolve(Attr uri, String BaseURI) { |
| 255 | if (uri == null) { |
| 256 | if (log.isLoggable(java.util.logging.Level.FINE)) { |
| 257 | log.log(java.util.logging.Level.FINE, "quick fail, uri == null"); |
| 258 | } |
| 259 | return false; |
| 260 | } |
| 261 | |
| 262 | String uriNodeValue = uri.getNodeValue(); |
| 263 | |
| 264 | if (uriNodeValue.equals("") || (uriNodeValue.charAt(0)=='#')) { |
| 265 | if (log.isLoggable(java.util.logging.Level.FINE)) { |
| 266 | log.log(java.util.logging.Level.FINE, |
| 267 | "quick fail for empty URIs and local ones"); |
| 268 | } |
| 269 | return false; |
| 270 | } |
| 271 | |
| 272 | if (log.isLoggable(java.util.logging.Level.FINE)) { |
| 273 | log.log(java.util.logging.Level.FINE, |
| 274 | "I was asked whether I can resolve " + uriNodeValue); |
| 275 | } |
| 276 | if ( uriNodeValue.startsWith("http:") || |
| 277 | BaseURI.startsWith("http:")) { |
| 278 | if (log.isLoggable(java.util.logging.Level.FINE)) { |
| 279 | log.log(java.util.logging.Level.FINE, |
| 280 | "I state that I can resolve " + uriNodeValue); |
| 281 | } |
| 282 | return true; |
| 283 | } |
| 284 | |
| 285 | if (log.isLoggable(java.util.logging.Level.FINE)) { |
| 286 | log.log(java.util.logging.Level.FINE, |
| 287 | "I state that I can't resolve " + uriNodeValue); |
| 288 | } |
| 289 | return false; |
| 290 | } |
| 291 | |
| 292 | /** |
| 293 | * @inheritDoc |
| 294 | */ |
| 295 | public String[] engineGetPropertyKeys() { |
| 296 | return (String[]) ResolverDirectHTTP.properties.clone(); |
| 297 | } |
| 298 | |
| 299 | private URI getNewURI(String uri, String BaseURI) |
| 300 | throws URI.MalformedURIException { |
| 301 | |
| 302 | if ((BaseURI == null) || "".equals(BaseURI)) { |
| 303 | return new URI(uri); |
| 304 | } |
| 305 | return new URI(new URI(BaseURI), uri); |
| 306 | } |
| 307 | } |