1 /* 2 * ==================================================================== 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * ==================================================================== 20 * 21 * This software consists of voluntary contributions made by many 22 * individuals on behalf of the Apache Software Foundation. For more 23 * information on the Apache Software Foundation, please see 24 * <http://www.apache.org/>. 25 * 26 */ 27 package org.apache.hc.client5.http.auth; 28 29 import java.io.Serializable; 30 import java.net.InetAddress; 31 import java.net.UnknownHostException; 32 import java.security.Principal; 33 import java.util.Locale; 34 import java.util.Objects; 35 36 import org.apache.hc.core5.annotation.Contract; 37 import org.apache.hc.core5.annotation.ThreadingBehavior; 38 import org.apache.hc.core5.util.Args; 39 import org.apache.hc.core5.util.LangUtils; 40 41 /** 42 * Microsoft Windows specific {@link Credentials} representation that includes 43 * Windows specific attributes such as name of the domain the user belongs to. 44 * 45 * @since 4.0 46 * 47 * @deprecated Do not use. the NTLM authentication scheme is no longer supported. 48 * Consider using Basic or Bearer authentication with TLS instead. 49 * 50 * @see UsernamePasswordCredentials 51 * @see BearerToken 52 */ 53 @Deprecated 54 @Contract(threading = ThreadingBehavior.IMMUTABLE) 55 public class NTCredentials implements Credentials, Serializable { 56 57 private static final long serialVersionUID = -7385699315228907265L; 58 59 /** The user principal */ 60 private final NTUserPrincipal principal; 61 62 /** Password */ 63 private final char[] password; 64 65 /** The netbios hostname the authentication request is originating from. */ 66 private final String workstation; 67 68 /** The netbios domain the authentication request is against */ 69 private final String netbiosDomain; 70 71 /** 72 * Constructor. 73 * @param userName The user name. This should not include the domain to authenticate with. 74 * For example: "user" is correct whereas "DOMAIN\user" is not. 75 * @param password The password. 76 * @param workstation The workstation the authentication request is originating from. 77 * Essentially, the computer name for this machine. 78 * @param domain The domain to authenticate within. 79 */ 80 public NTCredentials( 81 final String userName, 82 final char[] password, 83 final String workstation, 84 final String domain) { 85 this(password, userName, domain, convertDomain(domain)); 86 } 87 88 /** 89 * Constructor. 90 * @param userName The user name. This should not include the domain to authenticate with. 91 * For example: "user" is correct whereas "DOMAIN\user" is not. 92 * @param password The password. 93 * @param workstation The netbios workstation name that the authentication request is originating from. 94 * Essentially, the computer name for this machine. 95 * @param domain The domain to authenticate within. 96 * @param netbiosDomain The netbios version of the domain name. 97 */ 98 public NTCredentials( 99 final String userName, 100 final char[] password, 101 final String workstation, 102 final String domain, 103 final String netbiosDomain) { 104 this(password, userName, domain, netbiosDomain); 105 } 106 107 /** 108 * Constructor to create an instance of NTCredentials. 109 * 110 * @param password The password to use for authentication. Must not be null. 111 * @param userName The user name for authentication. This should not include the domain to authenticate with. 112 * For example: "user" is correct whereas "DOMAIN\user" is not. Must not be null. 113 * @param domain The domain to authenticate within. Can be null. 114 * @param netbiosDomain An alternative representation of the domain name in NetBIOS format. Can be null. 115 * This parameter is provided to accommodate specific scenarios that require the NetBIOS version of the domain name. 116 * <p> 117 * This constructor creates a new instance of NTCredentials, determining the workstation name at runtime 118 * using the {@link #getWorkstationName()} method. The workstation name will be converted to uppercase 119 * using the {@link java.util.Locale#ROOT} locale. 120 */ 121 public NTCredentials( 122 final char[] password, 123 final String userName, 124 final String domain, 125 final String netbiosDomain) { 126 super(); 127 Args.notNull(userName, "User name"); 128 this.principal = new NTUserPrincipal(domain, userName); 129 this.password = password; 130 this.workstation = getWorkstationName().toUpperCase(Locale.ROOT); 131 this.netbiosDomain = netbiosDomain; 132 } 133 134 135 @Override 136 public Principal getUserPrincipal() { 137 return this.principal; 138 } 139 140 public String getUserName() { 141 return this.principal.getUsername(); 142 } 143 144 @Override 145 public char[] getPassword() { 146 return this.password; 147 } 148 149 /** 150 * Retrieves the name to authenticate with. 151 * 152 * @return String the domain these credentials are intended to authenticate with. 153 */ 154 public String getDomain() { 155 return this.principal.getDomain(); 156 } 157 158 /** 159 * Retrieves the netbios domain to authenticate with. 160 * @return String the netbios domain name. 161 */ 162 public String getNetbiosDomain() { 163 return this.netbiosDomain; 164 } 165 166 /** 167 * Retrieves the netbios workstation name of the computer originating the request. 168 * 169 * @return String the netbios workstation the user is logged into. 170 */ 171 public String getWorkstation() { 172 return this.workstation; 173 } 174 175 @Override 176 public int hashCode() { 177 int hash = LangUtils.HASH_SEED; 178 hash = LangUtils.hashCode(hash, this.principal); 179 hash = LangUtils.hashCode(hash, this.workstation); 180 hash = LangUtils.hashCode(hash, this.netbiosDomain); 181 return hash; 182 } 183 184 @Override 185 public boolean equals(final Object o) { 186 if (this == o) { 187 return true; 188 } 189 if (o instanceof NTCredentials) { 190 final NTCredentials that = (NTCredentials) o; 191 return Objects.equals(this.principal, that.principal) 192 && Objects.equals(this.workstation, that.workstation) 193 && Objects.equals(this.netbiosDomain, that.netbiosDomain); 194 } 195 return false; 196 } 197 198 @Override 199 public String toString() { 200 final StringBuilder buffer = new StringBuilder(); 201 buffer.append("[principal: "); 202 buffer.append(this.principal); 203 buffer.append("][workstation: "); 204 buffer.append(this.workstation); 205 buffer.append("][netbiosDomain: "); 206 buffer.append(this.netbiosDomain); 207 buffer.append("]"); 208 return buffer.toString(); 209 } 210 211 /** Strip dot suffix from a name */ 212 private static String stripDotSuffix(final String value) { 213 if (value == null) { 214 return null; 215 } 216 final int index = value.indexOf('.'); 217 if (index != -1) { 218 return value.substring(0, index); 219 } 220 return value; 221 } 222 223 /** Convert domain to standard form */ 224 private static String convertDomain(final String domain) { 225 final String returnString = stripDotSuffix(domain); 226 return returnString == null ? returnString : returnString.toUpperCase(Locale.ROOT); 227 } 228 229 230 /** 231 * Retrieves the workstation name of the computer originating the request. 232 * This method attempts to get the local host name using the InetAddress class. 233 * If it fails to retrieve the host name due to an UnknownHostException, it returns "localhost" as a fallback. 234 * 235 * @return The unqualified workstation name as a String. 236 */ 237 private static String getWorkstationName() { 238 try { 239 final InetAddress addr = InetAddress.getLocalHost(); 240 final String hostName = addr.getHostName(); 241 // Ensure the hostname is unqualified by removing any domain part 242 return stripDotSuffix(hostName); 243 } catch (final UnknownHostException e) { 244 return "localhost"; 245 } 246 } 247 248 }