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