1 19 20 package jcifs.ntlmssp; 21 22 import java.io.IOException ; 23 24 import java.net.UnknownHostException ; 25 26 import java.security.SecureRandom ; 27 28 import jcifs.Config; 29 30 import jcifs.netbios.NbtAddress; 31 32 import jcifs.smb.NtlmPasswordAuthentication; 33 34 37 public class Type3Message extends NtlmMessage { 38 39 private static final int DEFAULT_FLAGS; 40 41 private static final String DEFAULT_DOMAIN; 42 43 private static final String DEFAULT_USER; 44 45 private static final String DEFAULT_PASSWORD; 46 47 private static final String DEFAULT_WORKSTATION; 48 49 private static final int LM_COMPATIBILITY; 50 51 private static final SecureRandom RANDOM = new SecureRandom (); 52 53 private byte[] lmResponse; 54 55 private byte[] ntResponse; 56 57 private String domain; 58 59 private String user; 60 61 private String workstation; 62 63 private byte[] sessionKey; 64 65 static { 66 DEFAULT_FLAGS = NTLMSSP_NEGOTIATE_NTLM | 67 (Config.getBoolean("jcifs.smb.client.useUnicode", true) ? 68 NTLMSSP_NEGOTIATE_UNICODE : NTLMSSP_NEGOTIATE_OEM); 69 DEFAULT_DOMAIN = Config.getProperty("jcifs.smb.client.domain", null); 70 DEFAULT_USER = Config.getProperty("jcifs.smb.client.username", null); 71 DEFAULT_PASSWORD = Config.getProperty("jcifs.smb.client.password", 72 null); 73 String defaultWorkstation = null; 74 try { 75 defaultWorkstation = NbtAddress.getLocalHost().getHostName(); 76 } catch (UnknownHostException ex) { } 77 DEFAULT_WORKSTATION = defaultWorkstation; 78 LM_COMPATIBILITY = Config.getInt("jcifs.smb.lmCompatibility", 0); 79 } 80 81 85 public Type3Message() { 86 setFlags(getDefaultFlags()); 87 setDomain(getDefaultDomain()); 88 setUser(getDefaultUser()); 89 setWorkstation(getDefaultWorkstation()); 90 } 91 92 98 public Type3Message(Type2Message type2) { 99 setFlags(getDefaultFlags(type2)); 100 setWorkstation(getDefaultWorkstation()); 101 String domain = getDefaultDomain(); 102 setDomain(domain); 103 String user = getDefaultUser(); 104 setUser(user); 105 String password = getDefaultPassword(); 106 switch (LM_COMPATIBILITY) { 107 case 0: 108 case 1: 109 setLMResponse(getLMResponse(type2, password)); 110 setNTResponse(getNTResponse(type2, password)); 111 break; 112 case 2: 113 byte[] nt = getNTResponse(type2, password); 114 setLMResponse(nt); 115 setNTResponse(nt); 116 break; 117 case 3: 118 case 4: 119 case 5: 120 byte[] clientChallenge = new byte[8]; 121 RANDOM.nextBytes(clientChallenge); 122 setLMResponse(getLMv2Response(type2, domain, user, password, 123 clientChallenge)); 124 128 break; 129 default: 130 setLMResponse(getLMResponse(type2, password)); 131 setNTResponse(getNTResponse(type2, password)); 132 } 133 } 134 135 145 public Type3Message(Type2Message type2, String password, String domain, 146 String user, String workstation) { 147 setFlags(getDefaultFlags(type2)); 148 setDomain(domain); 149 setUser(user); 150 setWorkstation(workstation); 151 switch (LM_COMPATIBILITY) { 152 case 0: 153 case 1: 154 setLMResponse(getLMResponse(type2, password)); 155 setNTResponse(getNTResponse(type2, password)); 156 break; 157 case 2: 158 byte[] nt = getNTResponse(type2, password); 159 setLMResponse(nt); 160 setNTResponse(nt); 161 break; 162 case 3: 163 case 4: 164 case 5: 165 byte[] clientChallenge = new byte[8]; 166 RANDOM.nextBytes(clientChallenge); 167 setLMResponse(getLMv2Response(type2, domain, user, password, 168 clientChallenge)); 169 173 break; 174 default: 175 setLMResponse(getLMResponse(type2, password)); 176 setNTResponse(getNTResponse(type2, password)); 177 } 178 } 179 180 191 public Type3Message(int flags, byte[] lmResponse, byte[] ntResponse, 192 String domain, String user, String workstation) { 193 setFlags(flags); 194 setLMResponse(lmResponse); 195 setNTResponse(ntResponse); 196 setDomain(domain); 197 setUser(user); 198 setWorkstation(workstation); 199 } 200 201 207 public Type3Message(byte[] material) throws IOException { 208 parse(material); 209 } 210 211 216 public byte[] getLMResponse() { 217 return lmResponse; 218 } 219 220 225 public void setLMResponse(byte[] lmResponse) { 226 this.lmResponse = lmResponse; 227 } 228 229 234 public byte[] getNTResponse() { 235 return ntResponse; 236 } 237 238 243 public void setNTResponse(byte[] ntResponse) { 244 this.ntResponse = ntResponse; 245 } 246 247 252 public String getDomain() { 253 return domain; 254 } 255 256 261 public void setDomain(String domain) { 262 this.domain = domain; 263 } 264 265 270 public String getUser() { 271 return user; 272 } 273 274 279 public void setUser(String user) { 280 this.user = user; 281 } 282 283 288 public String getWorkstation() { 289 return workstation; 290 } 291 292 297 public void setWorkstation(String workstation) { 298 this.workstation = workstation; 299 } 300 301 306 public byte[] getSessionKey() { 307 return sessionKey; 308 } 309 310 315 public void setSessionKey(byte[] sessionKey) { 316 this.sessionKey = sessionKey; 317 } 318 319 public byte[] toByteArray() { 320 try { 321 int flags = getFlags(); 322 boolean unicode = (flags & NTLMSSP_NEGOTIATE_UNICODE) != 0; 323 String oem = unicode ? null : getOEMEncoding(); 324 String domainName = getDomain(); 325 byte[] domain = null; 326 if (domainName != null && domainName.length() != 0) { 327 domain = unicode ? 328 domainName.toUpperCase().getBytes("UnicodeLittleUnmarked") : 329 domainName.toUpperCase().getBytes(oem); 330 } 331 int domainLength = (domain != null) ? domain.length : 0; 332 String userName = getUser(); 333 byte[] user = null; 334 if (userName != null && userName.length() != 0) { 335 user = unicode ? userName.getBytes("UnicodeLittleUnmarked") : 336 userName.toUpperCase().getBytes(oem); 337 } 338 int userLength = (user != null) ? user.length : 0; 339 String workstationName = getWorkstation(); 340 byte[] workstation = null; 341 if (workstationName != null && workstationName.length() != 0) { 342 workstation = unicode ? 343 workstationName.getBytes("UnicodeLittleUnmarked") : 344 workstationName.toUpperCase().getBytes(oem); 345 } 346 int workstationLength = (workstation != null) ? 347 workstation.length : 0; 348 byte[] lmResponse = getLMResponse(); 349 int lmLength = (lmResponse != null) ? lmResponse.length : 0; 350 byte[] ntResponse = getNTResponse(); 351 int ntLength = (ntResponse != null) ? ntResponse.length : 0; 352 byte[] sessionKey = getSessionKey(); 353 int keyLength = (sessionKey != null) ? sessionKey.length : 0; 354 byte[] type3 = new byte[64 + domainLength + userLength + 355 workstationLength + lmLength + ntLength + keyLength]; 356 System.arraycopy(NTLMSSP_SIGNATURE, 0, type3, 0, 8); 357 writeULong(type3, 8, 3); 358 int offset = 64; 359 writeSecurityBuffer(type3, 12, offset, lmResponse); 360 offset += lmLength; 361 writeSecurityBuffer(type3, 20, offset, ntResponse); 362 offset += ntLength; 363 writeSecurityBuffer(type3, 28, offset, domain); 364 offset += domainLength; 365 writeSecurityBuffer(type3, 36, offset, user); 366 offset += userLength; 367 writeSecurityBuffer(type3, 44, offset, workstation); 368 offset += workstationLength; 369 writeSecurityBuffer(type3, 52, offset, sessionKey); 370 writeULong(type3, 60, flags); 371 return type3; 372 } catch (IOException ex) { 373 throw new IllegalStateException (ex.getMessage()); 374 } 375 } 376 377 public String toString() { 378 String user = getUser(); 379 String domain = getDomain(); 380 String workstation = getWorkstation(); 381 byte[] lmResponse = getLMResponse(); 382 byte[] ntResponse = getNTResponse(); 383 byte[] sessionKey = getSessionKey(); 384 int flags = getFlags(); 385 StringBuffer buffer = new StringBuffer (); 386 if (domain != null) { 387 buffer.append("domain: ").append(domain); 388 } 389 if (user != null) { 390 if (buffer.length() > 0) buffer.append("; "); 391 buffer.append("user: ").append(user); 392 } 393 if (workstation != null) { 394 if (buffer.length() > 0) buffer.append("; "); 395 buffer.append("workstation: ").append(workstation); 396 } 397 if (lmResponse != null) { 398 if (buffer.length() > 0) buffer.append("; "); 399 buffer.append("lmResponse: "); 400 buffer.append("0x"); 401 for (int i = 0; i < lmResponse.length; i++) { 402 buffer.append(Integer.toHexString((lmResponse[i] >> 4) & 0x0f)); 403 buffer.append(Integer.toHexString(lmResponse[i] & 0x0f)); 404 } 405 } 406 if (ntResponse != null) { 407 if (buffer.length() > 0) buffer.append("; "); 408 buffer.append("ntResponse: "); 409 buffer.append("0x"); 410 for (int i = 0; i < ntResponse.length; i++) { 411 buffer.append(Integer.toHexString((ntResponse[i] >> 4) & 0x0f)); 412 buffer.append(Integer.toHexString(ntResponse[i] & 0x0f)); 413 } 414 } 415 if (sessionKey != null) { 416 if (buffer.length() > 0) buffer.append("; "); 417 buffer.append("sessionKey: "); 418 buffer.append("0x"); 419 for (int i = 0; i < sessionKey.length; i++) { 420 buffer.append(Integer.toHexString((sessionKey[i] >> 4) & 0x0f)); 421 buffer.append(Integer.toHexString(sessionKey[i] & 0x0f)); 422 } 423 } 424 if (flags != 0) { 425 if (buffer.length() > 0) buffer.append("; "); 426 buffer.append("flags: "); 427 buffer.append("0x"); 428 buffer.append(Integer.toHexString((flags >> 28) & 0x0f)); 429 buffer.append(Integer.toHexString((flags >> 24) & 0x0f)); 430 buffer.append(Integer.toHexString((flags >> 20) & 0x0f)); 431 buffer.append(Integer.toHexString((flags >> 16) & 0x0f)); 432 buffer.append(Integer.toHexString((flags >> 12) & 0x0f)); 433 buffer.append(Integer.toHexString((flags >> 8) & 0x0f)); 434 buffer.append(Integer.toHexString((flags >> 4) & 0x0f)); 435 buffer.append(Integer.toHexString(flags & 0x0f)); 436 } 437 return buffer.toString(); 438 } 439 440 446 public static int getDefaultFlags() { 447 return DEFAULT_FLAGS; 448 } 449 450 456 public static int getDefaultFlags(Type2Message type2) { 457 if (type2 == null) return DEFAULT_FLAGS; 458 int flags = NTLMSSP_NEGOTIATE_NTLM; 459 flags |= ((type2.getFlags() & NTLMSSP_NEGOTIATE_UNICODE) != 0) ? 460 NTLMSSP_NEGOTIATE_UNICODE : NTLMSSP_NEGOTIATE_OEM; 461 return flags; 462 } 463 464 472 public static byte[] getLMResponse(Type2Message type2, String password) { 473 if (type2 == null || password == null) return null; 474 return NtlmPasswordAuthentication.getPreNTLMResponse(password, 475 type2.getChallenge()); 476 } 477 478 public static byte[] getLMv2Response(Type2Message type2, 479 String domain, String user, String password, 480 byte[] clientChallenge) { 481 if (type2 == null || domain == null || user == null || 482 password == null || clientChallenge == null) { 483 return null; 484 } 485 return NtlmPasswordAuthentication.getLMv2Response(domain, user, 486 password, type2.getChallenge(), clientChallenge); 487 } 488 489 497 public static byte[] getNTResponse(Type2Message type2, String password) { 498 if (type2 == null || password == null) return null; 499 return NtlmPasswordAuthentication.getNTLMResponse(password, 500 type2.getChallenge()); 501 } 502 503 508 public static String getDefaultDomain() { 509 return DEFAULT_DOMAIN; 510 } 511 512 517 public static String getDefaultUser() { 518 return DEFAULT_USER; 519 } 520 521 526 public static String getDefaultPassword() { 527 return DEFAULT_PASSWORD; 528 } 529 530 535 public static String getDefaultWorkstation() { 536 return DEFAULT_WORKSTATION; 537 } 538 539 private void parse(byte[] material) throws IOException { 540 for (int i = 0; i < 8; i++) { 541 if (material[i] != NTLMSSP_SIGNATURE[i]) { 542 throw new IOException ("Not an NTLMSSP message."); 543 } 544 } 545 if (readULong(material, 8) != 3) { 546 throw new IOException ("Not a Type 3 message."); 547 } 548 byte[] lmResponse = readSecurityBuffer(material, 12); 549 int lmResponseOffset = readULong(material, 16); 550 byte[] ntResponse = readSecurityBuffer(material, 20); 551 int ntResponseOffset = readULong(material, 24); 552 byte[] domain = readSecurityBuffer(material, 28); 553 int domainOffset = readULong(material, 32); 554 byte[] user = readSecurityBuffer(material, 36); 555 int userOffset = readULong(material, 40); 556 byte[] workstation = readSecurityBuffer(material, 44); 557 int workstationOffset = readULong(material, 48); 558 int flags; 559 String charset; 560 if (lmResponseOffset == 52 || ntResponseOffset == 52 || 561 domainOffset == 52 || userOffset == 52 || 562 workstationOffset == 52) { 563 flags = NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_OEM; 564 charset = getOEMEncoding(); 565 } else { 566 setSessionKey(readSecurityBuffer(material, 52)); 567 flags = readULong(material, 60); 568 charset = ((flags & NTLMSSP_NEGOTIATE_UNICODE) != 0) ? 569 "UnicodeLittleUnmarked" : getOEMEncoding(); 570 } 571 setFlags(flags); 572 setLMResponse(lmResponse); 573 578 if (ntResponse.length == 24) setNTResponse(ntResponse); 579 setDomain(new String (domain, charset)); 580 setUser(new String (user, charset)); 581 setWorkstation(new String (workstation, charset)); 582 } 583 } 584 | Popular Tags |