1 /* 2 * Copyright (c) 2002, 2012, 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 sun.net.www.protocol.http.ntlm; 27 28 import java.io.IOException; 29 import java.net.InetAddress; 30 import java.net.PasswordAuthentication; 31 import java.net.UnknownHostException; 32 import java.net.URL; 33 import sun.net.www.HeaderParser; 34 import sun.net.www.protocol.http.AuthenticationInfo; 35 import sun.net.www.protocol.http.AuthScheme; 36 import sun.net.www.protocol.http.HttpURLConnection; 37 38 /** 39 * NTLMAuthentication: 40 * 41 * @author Michael McMahon 42 */ 43 44 public class NTLMAuthentication extends AuthenticationInfo { 45 46 private static final long serialVersionUID = 100L; 47 48 private static final NTLMAuthenticationCallback NTLMAuthCallback = 49 NTLMAuthenticationCallback.getNTLMAuthenticationCallback(); 50 51 private String hostname; 52 private static String defaultDomain; /* Domain to use if not specified by user */ 53 54 static { 55 defaultDomain = java.security.AccessController.doPrivileged( 56 new sun.security.action.GetPropertyAction("http.auth.ntlm.domain", 57 "domain")); 58 }; 59 60 private void init0() { 61 62 hostname = java.security.AccessController.doPrivileged( 63 new java.security.PrivilegedAction<String>() { 64 public String run() { 65 String localhost; 66 try { 67 localhost = InetAddress.getLocalHost().getHostName().toUpperCase(); 68 } catch (UnknownHostException e) { 69 localhost = "localhost"; 70 } 71 return localhost; 72 } 73 }); 74 int x = hostname.indexOf ('.'); 75 if (x != -1) { 76 hostname = hostname.substring (0, x); 77 } 78 } 79 80 String username; 81 String ntdomain; 82 String password; 83 84 /** 85 * Create a NTLMAuthentication: 86 * Username may be specified as domain<BACKSLASH>username in the application Authenticator. 87 * If this notation is not used, then the domain will be taken 88 * from a system property: "http.auth.ntlm.domain". 89 */ 90 public NTLMAuthentication(boolean isProxy, URL url, PasswordAuthentication pw) { 91 super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION, 92 AuthScheme.NTLM, 93 url, 94 ""); 95 init (pw); 96 } 97 98 private void init (PasswordAuthentication pw) { 99 this.pw = pw; 100 if (pw != null) { 101 String s = pw.getUserName(); 102 int i = s.indexOf ('\\'); 103 if (i == -1) { 104 username = s; 105 ntdomain = defaultDomain; 106 } else { 107 ntdomain = s.substring (0, i).toUpperCase(); 108 username = s.substring (i+1); 109 } 110 password = new String (pw.getPassword()); 111 } else { 112 /* credentials will be acquired from OS */ 113 username = null; 114 ntdomain = null; 115 password = null; 116 } 117 init0(); 118 } 119 120 /** 121 * Constructor used for proxy entries 122 */ 123 public NTLMAuthentication(boolean isProxy, String host, int port, 124 PasswordAuthentication pw) { 125 super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, 126 AuthScheme.NTLM, 127 host, 128 port, 129 ""); 130 init (pw); 131 } 132 133 /** 134 * @return true if this authentication supports preemptive authorization 135 */ 136 @Override 137 public boolean supportsPreemptiveAuthorization() { 138 return false; 139 } 140 141 /** 142 * @return true if NTLM supported transparently (no password needed, SSO) 143 */ 144 public static boolean supportsTransparentAuth() { 145 return true; 146 } 147 148 /** 149 * Returns true if the given site is trusted, i.e. we can try 150 * transparent Authentication. 151 */ 152 public static boolean isTrustedSite(URL url) { 153 return NTLMAuthCallback.isTrustedSite(url); 154 } 155 156 /** 157 * Not supported. Must use the setHeaders() method 158 */ 159 @Override 160 public String getHeaderValue(URL url, String method) { 161 throw new RuntimeException ("getHeaderValue not supported"); 162 } 163 164 /** 165 * Check if the header indicates that the current auth. parameters are stale. 166 * If so, then replace the relevant field with the new value 167 * and return true. Otherwise return false. 168 * returning true means the request can be retried with the same userid/password 169 * returning false means we have to go back to the user to ask for a new 170 * username password. 171 */ 172 @Override 173 public boolean isAuthorizationStale (String header) { 174 return false; /* should not be called for ntlm */ 175 } 176 177 /** 178 * Set header(s) on the given connection. 179 * @param conn The connection to apply the header(s) to 180 * @param p A source of header values for this connection, not used because 181 * HeaderParser converts the fields to lower case, use raw instead 182 * @param raw The raw header field. 183 * @return true if all goes well, false if no headers were set. 184 */ 185 @Override 186 public synchronized boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) { 187 188 try { 189 NTLMAuthSequence seq = (NTLMAuthSequence)conn.authObj(); 190 if (seq == null) { 191 seq = new NTLMAuthSequence (username, password, ntdomain); 192 conn.authObj(seq); 193 } 194 String response = "NTLM " + seq.getAuthHeader (raw.length()>6?raw.substring(5):null); 195 conn.setAuthenticationProperty(getHeaderName(), response); 196 if (seq.isComplete()) { 197 conn.authObj(null); 198 } 199 return true; 200 } catch (IOException e) { 201 conn.authObj(null); 202 return false; 203 } 204 } 205 206 }