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 {@literal domain<BACKSLASH>username} 87 * in the application Authenticator. 88 * If this notation is not used, then the domain will be taken 89 * from a system property: "http.auth.ntlm.domain". 90 */ 91 public NTLMAuthentication(boolean isProxy, URL url, PasswordAuthentication pw) { 92 super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION, 93 AuthScheme.NTLM, 94 url, 95 ""); 96 init (pw); 97 } 98 99 private void init (PasswordAuthentication pw) { 100 this.pw = pw; 101 if (pw != null) { 102 String s = pw.getUserName(); 103 int i = s.indexOf ('\\'); 104 if (i == -1) { 105 username = s; 106 ntdomain = defaultDomain; 107 } else { 108 ntdomain = s.substring (0, i).toUpperCase(); 109 username = s.substring (i+1); 110 } 111 password = new String (pw.getPassword()); 112 } else { 113 /* credentials will be acquired from OS */ 114 username = null; 115 ntdomain = null; 116 password = null; 117 } 118 init0(); 119 } 120 121 /** 122 * Constructor used for proxy entries 123 */ 124 public NTLMAuthentication(boolean isProxy, String host, int port, 125 PasswordAuthentication pw) { 126 super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, 127 AuthScheme.NTLM, 128 host, 129 port, 130 ""); 131 init (pw); 132 } 133 134 /** 135 * @return true if this authentication supports preemptive authorization 136 */ 137 @Override 138 public boolean supportsPreemptiveAuthorization() { 139 return false; 140 } 141 142 /** 143 * @return true if NTLM supported transparently (no password needed, SSO) 144 */ 145 public static boolean supportsTransparentAuth() { 146 return true; 147 } 148 149 /** 150 * Returns true if the given site is trusted, i.e. we can try 151 * transparent Authentication. 152 */ 153 public static boolean isTrustedSite(URL url) { 154 return NTLMAuthCallback.isTrustedSite(url); 155 } 156 157 /** 158 * Not supported. Must use the setHeaders() method 159 */ 160 @Override 161 public String getHeaderValue(URL url, String method) { 162 throw new RuntimeException ("getHeaderValue not supported"); 163 } 164 165 /** 166 * Check if the header indicates that the current auth. parameters are stale. 167 * If so, then replace the relevant field with the new value 168 * and return true. Otherwise return false. 169 * returning true means the request can be retried with the same userid/password 170 * returning false means we have to go back to the user to ask for a new 171 * username password. 172 */ 173 @Override 174 public boolean isAuthorizationStale (String header) { 175 return false; /* should not be called for ntlm */ 176 } 177 178 /** 179 * Set header(s) on the given connection. 180 * @param conn The connection to apply the header(s) to 181 * @param p A source of header values for this connection, not used because 182 * HeaderParser converts the fields to lower case, use raw instead 183 * @param raw The raw header field. 184 * @return true if all goes well, false if no headers were set. 185 */ 186 @Override 187 public synchronized boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) { 188 189 try { 190 NTLMAuthSequence seq = (NTLMAuthSequence)conn.authObj(); 191 if (seq == null) { 192 seq = new NTLMAuthSequence (username, password, ntdomain); 193 conn.authObj(seq); 194 } 195 String response = "NTLM " + seq.getAuthHeader (raw.length()>6?raw.substring(5):null); 196 conn.setAuthenticationProperty(getHeaderName(), response); 197 if (seq.isComplete()) { 198 conn.authObj(null); 199 } 200 return true; 201 } catch (IOException e) { 202 conn.authObj(null); 203 return false; 204 } 205 } 206 207 }