1 /* 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.istack.internal.tools; 27 28 import java.io.BufferedReader; 29 import java.io.File; 30 import java.io.FileInputStream; 31 import java.io.FileNotFoundException; 32 import java.io.IOException; 33 import java.io.InputStreamReader; 34 import java.io.UnsupportedEncodingException; 35 import java.lang.reflect.Field; 36 import java.net.Authenticator; 37 import java.net.Authenticator.RequestorType; 38 import java.net.MalformedURLException; 39 import java.net.PasswordAuthentication; 40 import java.net.URL; 41 import java.net.URLDecoder; 42 import java.net.URLEncoder; 43 import java.security.AccessController; 44 import java.security.PrivilegedAction; 45 import java.util.ArrayList; 46 import java.util.List; 47 import java.util.logging.Level; 48 import java.util.logging.Logger; 49 import java.util.regex.Pattern; 50 import org.xml.sax.Locator; 51 import org.xml.sax.helpers.LocatorImpl; 52 53 /** 54 * @author Vivek Pandey 55 * @author Lukas Jungmann 56 */ 57 public class DefaultAuthenticator extends Authenticator { 58 59 private static DefaultAuthenticator instance; 60 private static Authenticator systemAuthenticator = getCurrentAuthenticator(); 61 private String proxyUser; 62 private String proxyPasswd; 63 private final List<AuthInfo> authInfo = new ArrayList<AuthInfo>(); 64 private static int counter = 0; 65 66 DefaultAuthenticator() { 67 //try undocumented but often used properties 68 if (System.getProperty("http.proxyUser") != null) { 69 proxyUser = System.getProperty("http.proxyUser"); 70 } else { 71 proxyUser = System.getProperty("proxyUser"); 72 } 73 if (System.getProperty("http.proxyPassword") != null) { 74 proxyPasswd = System.getProperty("http.proxyPassword"); 75 } else { 76 proxyPasswd = System.getProperty("proxyPassword"); 77 } 78 } 79 80 public static synchronized DefaultAuthenticator getAuthenticator() { 81 if (instance == null) { 82 instance = new DefaultAuthenticator(); 83 Authenticator.setDefault(instance); 128 } else { 129 this.proxyUser = proxyAuth.substring(0, i); 130 this.proxyPasswd = proxyAuth.substring(i + 1); 131 } 132 } 133 } 134 135 public void setAuth(File f, Receiver l) { 136 Receiver listener = l == null ? new DefaultRImpl() : l; 137 BufferedReader in = null; 138 FileInputStream fi = null; 139 InputStreamReader is = null; 140 try { 141 String text; 142 LocatorImpl locator = new LocatorImpl(); 143 locator.setSystemId(f.getAbsolutePath()); 144 try { 145 fi = new FileInputStream(f); 146 is = new InputStreamReader(fi, "UTF-8"); 147 in = new BufferedReader(is); 148 } catch (UnsupportedEncodingException e) { 149 listener.onError(e, locator); 150 return; 151 } catch (FileNotFoundException e) { 152 listener.onError(e, locator); 153 return; 154 } 155 try { 156 int lineno = 1; 157 locator.setSystemId(f.getCanonicalPath()); 158 while ((text = in.readLine()) != null) { 159 locator.setLineNumber(lineno++); 160 //ignore empty lines and treat those starting with '#' as comments 161 if ("".equals(text.trim()) || text.startsWith("#")) { 162 continue; 163 } 164 try { 165 AuthInfo ai = parseLine(text); 166 authInfo.add(ai); 167 } catch (Exception e) { 168 listener.onParsingError(text, locator); 169 } 170 } 171 } catch (IOException e) { 172 listener.onError(e, locator); 173 Logger.getLogger(DefaultAuthenticator.class.getName()).log(Level.SEVERE, e.getMessage(), e); 174 } 175 } finally { 176 try { 177 if (in != null) { 178 in.close(); 179 } 180 if (is != null) { 181 is.close(); 182 } 183 if (fi != null) { 184 fi.close(); 185 } 186 } catch (IOException ex) { 187 Logger.getLogger(DefaultAuthenticator.class.getName()).log(Level.SEVERE, null, ex); 188 } 189 } 190 } 191 192 private AuthInfo parseLine(String text) throws Exception { 193 URL url; 194 try { 195 url = new URL(text); 196 } catch (MalformedURLException mue) { 197 //possible cause of this can be that password contains 198 //character which has to be encoded in URL, 199 //such as '@', ')', '#' and few others 200 //so try to recreate the URL with encoded string 201 //between 2nd ':' and last '@' 202 int i = text.indexOf(':', text.indexOf(':') + 1) + 1; 203 int j = text.lastIndexOf('@'); 204 String encodedUrl = 205 text.substring(0, i) 206 + URLEncoder.encode(text.substring(i, j), "UTF-8") 207 + text.substring(j); 208 url = new URL(encodedUrl); 209 } 210 211 String authinfo = url.getUserInfo(); 212 213 if (authinfo != null) { 214 int i = authinfo.indexOf(':'); 215 216 if (i >= 0) { 217 String user = authinfo.substring(0, i); 218 String password = authinfo.substring(i + 1); 219 return new AuthInfo( 220 new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getFile()), 221 user, URLDecoder.decode(password, "UTF-8")); 222 } 223 } 224 throw new Exception(); 225 } 226 227 static Authenticator getCurrentAuthenticator() { 228 final Field f = getTheAuthenticator(); 229 if (f == null) { 230 return null; 231 } 232 233 try { 234 AccessController.doPrivileged(new PrivilegedAction<Void>() { 235 @Override 236 public Void run() { 237 f.setAccessible(true); 238 return null; 239 } 240 }); 241 return (Authenticator) f.get(null); 242 } catch (Exception ex) { 243 return null; 244 } finally { 245 AccessController.doPrivileged(new PrivilegedAction<Void>() { 246 @Override 247 public Void run() { 248 f.setAccessible(false); 249 return null; 250 } 251 }); 252 } 253 } 254 255 private static Field getTheAuthenticator() { 256 try { 257 return Authenticator.class.getDeclaredField("theAuthenticator"); 258 } catch (Exception ex) { 259 return null; 260 } 261 } 262 263 public static interface Receiver { 264 265 void onParsingError(String line, Locator loc); 266 267 void onError(Exception e, Locator loc); 268 } 269 270 private static class DefaultRImpl implements Receiver { 271 272 @Override 273 public void onParsingError(String line, Locator loc) { 274 System.err.println(getLocationString(loc) + ": " + line); 275 } 276 277 @Override 278 public void onError(Exception e, Locator loc) { 279 System.err.println(getLocationString(loc) + ": " + e.getMessage()); 280 Logger.getLogger(DefaultAuthenticator.class.getName()).log(Level.SEVERE, e.getMessage(), e); 281 } 282 283 private String getLocationString(Locator l) { 284 return "[" + l.getSystemId() + "#" + l.getLineNumber() + "]"; 285 } 286 } 287 288 /** 289 * Represents authorization information needed by 290 * {@link DefaultAuthenticator} to authenticate access to remote resources. 291 * 292 * @author Vivek Pandey 293 * @author Lukas Jungmann 294 */ 295 final static class AuthInfo { 296 297 private final String user; 298 private final String password; 299 private final Pattern urlPattern; 300 | 1 /* 2 * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.istack.internal.tools; 27 28 import java.io.BufferedReader; 29 import java.io.File; 30 import java.io.FileInputStream; 31 import java.io.FileNotFoundException; 32 import java.io.IOException; 33 import java.io.InputStreamReader; 34 import java.io.UnsupportedEncodingException; 35 import java.lang.reflect.Field; 36 import java.lang.reflect.Method; 37 import java.net.Authenticator; 38 import java.net.Authenticator.RequestorType; 39 import java.net.MalformedURLException; 40 import java.net.PasswordAuthentication; 41 import java.net.URL; 42 import java.net.URLDecoder; 43 import java.net.URLEncoder; 44 import java.security.AccessController; 45 import java.security.PrivilegedAction; 46 import java.security.PrivilegedActionException; 47 import java.security.PrivilegedExceptionAction; 48 import java.util.ArrayList; 49 import java.util.List; 50 import java.util.logging.Level; 51 import java.util.logging.Logger; 52 import java.util.regex.Pattern; 53 import org.xml.sax.Locator; 54 import org.xml.sax.helpers.LocatorImpl; 55 56 /** 57 * @author Vivek Pandey 58 * @author Lukas Jungmann 59 */ 60 public class DefaultAuthenticator extends Authenticator { 61 62 private static final Logger LOGGER = Logger.getLogger(DefaultAuthenticator.class.getName()); 63 private static DefaultAuthenticator instance; 64 private static Authenticator systemAuthenticator = getCurrentAuthenticator(); 65 private String proxyUser; 66 private String proxyPasswd; 67 private final List<AuthInfo> authInfo = new ArrayList<>(); 68 private static int counter = 0; 69 70 DefaultAuthenticator() { 71 //try undocumented but often used properties 72 if (System.getProperty("http.proxyUser") != null) { 73 proxyUser = System.getProperty("http.proxyUser"); 74 } else { 75 proxyUser = System.getProperty("proxyUser"); 76 } 77 if (System.getProperty("http.proxyPassword") != null) { 78 proxyPasswd = System.getProperty("http.proxyPassword"); 79 } else { 80 proxyPasswd = System.getProperty("proxyPassword"); 81 } 82 } 83 84 public static synchronized DefaultAuthenticator getAuthenticator() { 85 if (instance == null) { 86 instance = new DefaultAuthenticator(); 87 Authenticator.setDefault(instance); 132 } else { 133 this.proxyUser = proxyAuth.substring(0, i); 134 this.proxyPasswd = proxyAuth.substring(i + 1); 135 } 136 } 137 } 138 139 public void setAuth(File f, Receiver l) { 140 Receiver listener = l == null ? new DefaultRImpl() : l; 141 BufferedReader in = null; 142 FileInputStream fi = null; 143 InputStreamReader is = null; 144 try { 145 String text; 146 LocatorImpl locator = new LocatorImpl(); 147 locator.setSystemId(f.getAbsolutePath()); 148 try { 149 fi = new FileInputStream(f); 150 is = new InputStreamReader(fi, "UTF-8"); 151 in = new BufferedReader(is); 152 } catch (UnsupportedEncodingException | FileNotFoundException e) { 153 listener.onError(e, locator); 154 return; 155 } 156 try { 157 int lineno = 1; 158 locator.setSystemId(f.getCanonicalPath()); 159 while ((text = in.readLine()) != null) { 160 locator.setLineNumber(lineno++); 161 //ignore empty lines and treat those starting with '#' as comments 162 if ("".equals(text.trim()) || text.startsWith("#")) { 163 continue; 164 } 165 try { 166 AuthInfo ai = parseLine(text); 167 authInfo.add(ai); 168 } catch (Exception e) { 169 listener.onParsingError(text, locator); 170 } 171 } 172 } catch (IOException e) { 173 listener.onError(e, locator); 174 LOGGER.log(Level.SEVERE, e.getMessage(), e); 175 } 176 } finally { 177 try { 178 if (in != null) { 179 in.close(); 180 } 181 if (is != null) { 182 is.close(); 183 } 184 if (fi != null) { 185 fi.close(); 186 } 187 } catch (IOException ex) { 188 LOGGER.log(Level.SEVERE, null, ex); 189 } 190 } 191 } 192 193 private AuthInfo parseLine(String text) throws Exception { 194 URL url; 195 try { 196 url = new URL(text); 197 } catch (MalformedURLException mue) { 198 //possible cause of this can be that password contains 199 //character which has to be encoded in URL, 200 //such as '@', ')', '#' and few others 201 //so try to recreate the URL with encoded string 202 //between 2nd ':' and last '@' 203 int i = text.indexOf(':', text.indexOf(':') + 1) + 1; 204 int j = text.lastIndexOf('@'); 205 String encodedUrl = 206 text.substring(0, i) 207 + URLEncoder.encode(text.substring(i, j), "UTF-8") 208 + text.substring(j); 209 url = new URL(encodedUrl); 210 } 211 212 String authinfo = url.getUserInfo(); 213 214 if (authinfo != null) { 215 int i = authinfo.indexOf(':'); 216 217 if (i >= 0) { 218 String user = authinfo.substring(0, i); 219 String password = authinfo.substring(i + 1); 220 return new AuthInfo( 221 new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getFile()), 222 user, URLDecoder.decode(password, "UTF-8")); 223 } 224 } 225 throw new Exception(); 226 } 227 228 static Authenticator getCurrentAuthenticator() { 229 try { 230 return AccessController.doPrivileged(new PrivilegedExceptionAction<Authenticator>() { 231 @Override 232 public Authenticator run() throws Exception { 233 Method method = Authenticator.class.getMethod("getDefault"); 234 return (Authenticator) method.invoke(null); 235 } 236 237 }); 238 } catch (PrivilegedActionException pae) { 239 if (LOGGER.isLoggable(Level.FINE)) { 240 LOGGER.log(Level.FINE, null, pae); 241 } 242 Exception ex = pae.getException(); 243 if (!(ex instanceof NoSuchMethodException)) { 244 // if Authenticator.getDefault has not been found, 245 // we likely didn't get through sec, so return null 246 // and don't care about JDK version we're on 247 return null; 248 } 249 // or we're on JDK <9, so let's continue the old way... 250 } 251 252 final Field f = getTheAuthenticator(); 253 if (f == null) { 254 return null; 255 } 256 257 try { 258 AccessController.doPrivileged(new PrivilegedAction<Void>() { 259 @Override 260 public Void run() { 261 f.setAccessible(true); 262 return null; 263 } 264 }); 265 return (Authenticator) f.get(null); 266 } catch (IllegalAccessException | IllegalArgumentException ex) { 267 return null; 268 } finally { 269 AccessController.doPrivileged(new PrivilegedAction<Void>() { 270 @Override 271 public Void run() { 272 f.setAccessible(false); 273 return null; 274 } 275 }); 276 } 277 } 278 279 private static Field getTheAuthenticator() { 280 try { 281 return Authenticator.class.getDeclaredField("theAuthenticator"); 282 } catch (NoSuchFieldException | SecurityException ex) { 283 return null; 284 } 285 } 286 287 public static interface Receiver { 288 289 void onParsingError(String line, Locator loc); 290 291 void onError(Exception e, Locator loc); 292 } 293 294 private static class DefaultRImpl implements Receiver { 295 296 @Override 297 public void onParsingError(String line, Locator loc) { 298 System.err.println(getLocationString(loc) + ": " + line); 299 } 300 301 @Override 302 public void onError(Exception e, Locator loc) { 303 System.err.println(getLocationString(loc) + ": " + e.getMessage()); 304 LOGGER.log(Level.SEVERE, e.getMessage(), e); 305 } 306 307 private String getLocationString(Locator l) { 308 return "[" + l.getSystemId() + "#" + l.getLineNumber() + "]"; 309 } 310 } 311 312 /** 313 * Represents authorization information needed by 314 * {@link DefaultAuthenticator} to authenticate access to remote resources. 315 * 316 * @author Vivek Pandey 317 * @author Lukas Jungmann 318 */ 319 final static class AuthInfo { 320 321 private final String user; 322 private final String password; 323 private final Pattern urlPattern; 324 |