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.utils.resolver.implementations; 22 23 import java.io.ByteArrayOutputStream; 24 import java.io.IOException; 25 import java.io.InputStream; 26 import java.net.MalformedURLException; 27 import java.net.URL; 28 import java.net.URLConnection; 29 30 import com.sun.org.apache.xml.internal.utils.URI; 31 import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; 32 import com.sun.org.apache.xml.internal.security.utils.Base64; 33 import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException; 34 import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverSpi; 35 import org.w3c.dom.Attr; 36 37 38 /** 39 * A simple ResourceResolver for HTTP requests. This class handles only 'pure' 40 * HTTP URIs which means without a fragment. The Fragment handling is done by the 41 * {@link ResolverFragment} class. 42 * <BR> 43 * If the user has a corporate HTTP proxy which is to be used, the usage can be 44 * switched on by setting properties for the resolver: 45 * <PRE> 46 * resourceResolver.setProperty("http.proxy.host", "proxy.company.com"); 47 * resourceResolver.setProperty("http.proxy.port", "8080"); 48 * 49 * // if we need a password for the proxy 50 * resourceResolver.setProperty("http.proxy.username", "proxyuser3"); 51 * resourceResolver.setProperty("http.proxy.password", "secretca"); 52 * </PRE> 53 * 54 * 55 * @author $Author: mullan $ 56 * @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> 57 * @see <A HREF="http://java.sun.com/j2se/1.4/docs/guide/net/properties.html">SUN J2SE docs for network properties</A> 58 * @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> 59 * $todo$ the proxy behaviour seems not to work; if a on-existing proxy is set, it works ?!? 60 */ 61 public class ResolverDirectHTTP extends ResourceResolverSpi { 62 63 /** {@link java.util.logging} logging facility */ 64 static java.util.logging.Logger log = 65 java.util.logging.Logger.getLogger( 66 ResolverDirectHTTP.class.getName()); 67 68 /** Field properties[] */ 69 private static final String properties[] = 70 { "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 public boolean engineIsThreadSafe() { 95 return true; 96 } 97 /** 98 * Method resolve 99 * 100 * @param uri 101 * @param BaseURI 102 * 103 * @throws ResourceResolverException 104 * @return 105 * $todo$ calculate the correct URI from the attribute and the BaseURI 106 */ 107 public XMLSignatureInput engineResolve(Attr uri, String BaseURI) 108 throws ResourceResolverException { 109 110 try { 111 boolean useProxy = false; 112 String proxyHost = 113 engineGetProperty(ResolverDirectHTTP 114 .properties[ResolverDirectHTTP.HttpProxyHost]); 115 String proxyPort = 116 engineGetProperty(ResolverDirectHTTP 117 .properties[ResolverDirectHTTP.HttpProxyPort]); 118 119 if ((proxyHost != null) && (proxyPort != null)) { 120 useProxy = true; 121 } 122 123 String oldProxySet = null; 124 String oldProxyHost = null; 125 String oldProxyPort = null; 126 // switch on proxy usage 127 if (useProxy) { 128 if (log.isLoggable(java.util.logging.Level.FINE)) { 129 log.log(java.util.logging.Level.FINE, "Use of HTTP proxy enabled: " + proxyHost + ":" 130 + proxyPort); 131 } 132 oldProxySet = System.getProperty("http.proxySet"); 133 oldProxyHost = System.getProperty("http.proxyHost"); 134 oldProxyPort = System.getProperty("http.proxyPort"); 135 System.setProperty("http.proxySet", "true"); 136 System.setProperty("http.proxyHost", proxyHost); 137 System.setProperty("http.proxyPort", proxyPort); 138 } 139 140 boolean switchBackProxy = ((oldProxySet != null) 141 && (oldProxyHost != null) 142 && (oldProxyPort != null)); 143 144 // calculate new URI 145 URI uriNew = getNewURI(uri.getNodeValue(), BaseURI); 146 147 // if the URI contains a fragment, ignore it 148 URI uriNewNoFrag = new URI(uriNew); 149 150 uriNewNoFrag.setFragment(null); 151 152 URL url = new URL(uriNewNoFrag.toString()); 153 URLConnection urlConnection = url.openConnection(); 154 155 { 156 157 // set proxy pass 158 String proxyUser = 159 engineGetProperty(ResolverDirectHTTP 160 .properties[ResolverDirectHTTP.HttpProxyUser]); 161 String proxyPass = 162 engineGetProperty(ResolverDirectHTTP 163 .properties[ResolverDirectHTTP.HttpProxyPass]); 164 165 if ((proxyUser != null) && (proxyPass != null)) { 166 String password = proxyUser + ":" + proxyPass; 167 String encodedPassword = Base64.encode(password.getBytes()); 168 169 // or was it Proxy-Authenticate ? 170 urlConnection.setRequestProperty("Proxy-Authorization", 171 encodedPassword); 172 } 173 } 174 175 { 176 177 // check if Basic authentication is required 178 String auth = urlConnection.getHeaderField("WWW-Authenticate"); 179 180 if (auth != null) { 181 182 // do http basic authentication 183 if (auth.startsWith("Basic")) { 184 String user = 185 engineGetProperty(ResolverDirectHTTP 186 .properties[ResolverDirectHTTP.HttpBasicUser]); 187 String pass = 188 engineGetProperty(ResolverDirectHTTP 189 .properties[ResolverDirectHTTP.HttpBasicPass]); 190 191 if ((user != null) && (pass != null)) { 192 urlConnection = url.openConnection(); 193 194 String password = user + ":" + pass; 195 String encodedPassword = 196 Base64.encode(password.getBytes()); 197 198 // set authentication property in the http header 199 urlConnection.setRequestProperty("Authorization", 200 "Basic " 201 + encodedPassword); 202 } 203 } 204 } 205 } 206 207 String mimeType = urlConnection.getHeaderField("Content-Type"); 208 InputStream inputStream = urlConnection.getInputStream(); 209 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 210 byte buf[] = new byte[4096]; 211 int read = 0; 212 int summarized = 0; 213 214 while ((read = inputStream.read(buf)) >= 0) { 215 baos.write(buf, 0, read); 216 217 summarized += read; 218 } 219 220 log.log(java.util.logging.Level.FINE, "Fetched " + summarized + " bytes from URI " 221 + uriNew.toString()); 222 223 XMLSignatureInput result = new XMLSignatureInput(baos.toByteArray()); 224 225 // XMLSignatureInput result = new XMLSignatureInput(inputStream); 226 result.setSourceURI(uriNew.toString()); 227 result.setMIMEType(mimeType); 228 229 // switch off proxy usage 230 if (useProxy && switchBackProxy) { 231 System.setProperty("http.proxySet", oldProxySet); 232 System.setProperty("http.proxyHost", oldProxyHost); 233 System.setProperty("http.proxyPort", oldProxyPort); 234 } 235 236 return result; 237 } catch (MalformedURLException ex) { 238 throw new ResourceResolverException("generic.EmptyMessage", ex, uri, 239 BaseURI); 240 } catch (IOException ex) { 241 throw new ResourceResolverException("generic.EmptyMessage", ex, uri, 242 BaseURI); 243 } 244 } 245 246 /** 247 * We resolve http URIs <I>without</I> fragment... 248 * 249 * @param uri 250 * @param BaseURI 251 * @return true if can be resolved 252 */ 253 public boolean engineCanResolve(Attr uri, String BaseURI) { 254 if (uri == null) { 255 log.log(java.util.logging.Level.FINE, "quick fail, uri == null"); 256 257 return false; 258 } 259 260 String uriNodeValue = uri.getNodeValue(); 261 262 if (uriNodeValue.equals("") || (uriNodeValue.charAt(0)=='#')) { 263 log.log(java.util.logging.Level.FINE, "quick fail for empty URIs and local ones"); 264 265 return false; 266 } 267 268 if (log.isLoggable(java.util.logging.Level.FINE)) { 269 log.log(java.util.logging.Level.FINE, "I was asked whether I can resolve " + uriNodeValue); 270 } 271 272 if ( uriNodeValue.startsWith("http:") || 273 (BaseURI!=null && BaseURI.startsWith("http:") )) { 274 if (log.isLoggable(java.util.logging.Level.FINE)) { 275 log.log(java.util.logging.Level.FINE, "I state that I can resolve " + uriNodeValue); 276 } 277 278 return true; 279 } 280 281 if (log.isLoggable(java.util.logging.Level.FINE)) { 282 log.log(java.util.logging.Level.FINE, "I state that I can't resolve " + uriNodeValue); 283 } 284 285 return false; 286 } 287 288 /** 289 * @inheritDoc 290 */ 291 public String[] engineGetPropertyKeys() { 292 return ResolverDirectHTTP.properties.clone(); 293 } 294 295 private URI getNewURI(String uri, String BaseURI) 296 throws URI.MalformedURIException { 297 298 if ((BaseURI == null) || "".equals(BaseURI)) { 299 return new URI(uri); 300 } 301 return new URI(new URI(BaseURI), uri); 302 } 303 }