1 19 20 package com.knowgate.jcifs.smb; 21 22 import com.knowgate.jcifs.netbios.NbtSocket; 23 import com.knowgate.jcifs.netbios.NbtException; 24 import com.knowgate.jcifs.netbios.NbtAddress; 25 import com.knowgate.jcifs.UniAddress; 26 import com.knowgate.jcifs.Config; 27 import com.knowgate.debug.*; 28 29 import java.io.InputStream ; 30 import java.io.OutputStream ; 31 import java.io.PushbackInputStream ; 32 import java.io.IOException ; 33 import java.io.InterruptedIOException ; 34 import java.net.InetAddress ; 35 import java.net.SocketException ; 36 import java.net.UnknownHostException ; 37 38 import java.security.MessageDigest ; 39 40 import java.util.Arrays ; 41 import java.util.LinkedList ; 42 import java.util.ListIterator ; 43 import java.util.Enumeration ; 44 import java.util.HashMap ; 45 46 47 class SmbTransport implements Runnable { 48 49 private static final int DEFAULT_MAX_MPX_COUNT = 10; 50 private static final int DEFAULT_RESPONSE_TIMEOUT = 10000; 51 private static final int DEFAULT_SO_TIMEOUT = 15000; 52 private static final int DEFAULT_RCV_BUF_SIZE = 60416; 53 private static final int DEFAULT_SND_BUF_SIZE = 5000; 54 private static final int DEFAULT_SSN_LIMIT = 250; 55 56 private static final InetAddress LADDR = Config.getInetAddress( "jcifs.smb.client.laddr", null ); 57 private static final int LPORT = Config.getInt( "jcifs.smb.client.lport", 0 ); 58 private static final int SSN_LIMIT = Config.getInt( "jcifs.smb.client.ssnLimit", DEFAULT_SSN_LIMIT ); 59 private static final int MAX_MPX_COUNT = Config.getInt( "jcifs.smb.client.maxMpxCount", DEFAULT_MAX_MPX_COUNT ); 60 private static final int SND_BUF_SIZE = Config.getInt( "jcifs.smb.client.snd_buf_size", DEFAULT_SND_BUF_SIZE ); 61 private static final int RCV_BUF_SIZE = Config.getInt( "jcifs.smb.client.rcv_buf_size", DEFAULT_RCV_BUF_SIZE ); 62 private static final boolean USE_UNICODE = Config.getBoolean( "jcifs.smb.client.useUnicode", true ); 63 private static final boolean FORCE_UNICODE = Config.getBoolean( "jcifs.smb.client.useUnicode", false ); 64 private static final boolean USE_NTSTATUS = Config.getBoolean( "jcifs.smb.client.useNtStatus", true ); 65 private static final boolean SIGNPREF = Config.getBoolean("jcifs.smb.client.signingPreferred", false ); 66 private static final boolean USE_NTSMBS = Config.getBoolean( "jcifs.smb.client.useNTSmbs", true ); 67 private static final int DEFAULT_FLAGS2 = 68 ServerMessageBlock.FLAGS2_LONG_FILENAMES | 69 ServerMessageBlock.FLAGS2_EXTENDED_ATTRIBUTES | 70 ( SIGNPREF ? ServerMessageBlock.FLAGS2_SECURITY_SIGNATURES : 0 ) | 71 ( USE_NTSTATUS ? ServerMessageBlock.FLAGS2_STATUS32 : 0 ) | 72 ( USE_UNICODE ? ServerMessageBlock.FLAGS2_UNICODE : 0 ); 73 private static final int DEFAULT_CAPABILITIES = 74 ( USE_NTSMBS ? ServerMessageBlock.CAP_NT_SMBS : 0 ) | 75 ( USE_NTSTATUS ? ServerMessageBlock.CAP_STATUS32 : 0 ) | 76 ( USE_UNICODE ? ServerMessageBlock.CAP_UNICODE : 0 ) | 77 ServerMessageBlock.CAP_DFS; 78 private static final int FLAGS2 = Config.getInt( "jcifs.smb.client.flags2", DEFAULT_FLAGS2 ); 79 private static final int CAPABILITIES = Config.getInt( "jcifs.smb.client.capabilities", DEFAULT_CAPABILITIES ); 80 private static final int SO_TIMEOUT = Config.getInt( "jcifs.smb.client.soTimeout", DEFAULT_SO_TIMEOUT ); 81 private static final boolean TCP_NODELAY = Config.getBoolean( "jcifs.smb.client.tcpNoDelay", false ); 82 private static final int RESPONSE_TIMEOUT = 83 Config.getInt( "jcifs.smb.client.responseTimeout", DEFAULT_RESPONSE_TIMEOUT ); 84 85 private static final int PUSHBACK_BUF_SIZE = 64; 86 private static final int MID_OFFSET = 30; 87 private static final int FLAGS_RESPONSE = 0x80; 88 private static final int ST_GROUND = 0; 89 private static final int ST_NEGOTIATING = 1; 90 private static final LinkedList CONNECTIONS = new LinkedList (); 91 private static final int MAGIC[] = { 0xFF, 'S', 'M', 'B' }; 92 93 private static byte[] snd_buf = new byte[0xFFFF]; 94 private static byte[] rcv_buf = new byte[0xFFFF]; 95 96 private NbtSocket socket; 97 private HashMap responseTable; 98 private InputStream in; 99 private OutputStream out; 100 private int localPort; 101 private InetAddress localAddr; 102 private Thread thread; 103 private Object outLock; 104 private UniAddress address; 105 private int port; 106 private LinkedList sessions; 107 private LinkedList referrals = new LinkedList (); 108 private int state; 109 private Mid[] mids = new Mid[MAX_MPX_COUNT]; 110 private short mid_next; 111 112 static final String NATIVE_OS = 113 Config.getProperty( "jcifs.smb.client.nativeOs", System.getProperty( "os.name" )); 114 static final String NATIVE_LANMAN = 115 Config.getProperty( "jcifs.smb.client.nativeLanMan", "jCIFS" ); 116 static final int VC_NUMBER = 1; 117 118 static final SmbTransport NULL_TRANSPORT = new SmbTransport(); 119 120 class Mid { 121 short mid; 122 123 public int hashCode() { 124 return mid; 125 } 126 public boolean equals( Object obj ) { 127 return ((Mid)obj).mid == mid; 128 } 129 } 130 class ServerData { 131 byte flags; 132 int flags2; 133 int maxMpxCount; 134 int maxBufferSize; 135 int sessionKey; 136 int capabilities; 138 String oemDomainName; 139 int securityMode; 140 int security; 141 boolean encryptedPasswords; 142 boolean signaturesEnabled; 143 boolean signaturesRequired; 144 int maxNumberVcs; 145 int maxRawSize; 146 long serverTime; 147 int serverTimeZone; 148 int encryptionKeyLength; 149 byte[] encryptionKey; 150 } 151 152 int flags2 = FLAGS2; 153 int maxMpxCount = MAX_MPX_COUNT; 154 int snd_buf_size = SND_BUF_SIZE; 155 int rcv_buf_size = RCV_BUF_SIZE; 156 int capabilities = CAPABILITIES; 157 int sessionKey = 0x00000000; 158 boolean useUnicode = USE_UNICODE; 159 String tconHostName; 160 ServerData server; 161 SigningDigest digest = null; 162 163 static synchronized SmbTransport getSmbTransport( UniAddress address, int port ) { 164 return getSmbTransport( address, port, LADDR, LPORT ); 165 } 166 static synchronized SmbTransport getSmbTransport( UniAddress address, int port, 167 InetAddress localAddr, int localPort ) { 168 SmbTransport conn; 169 170 synchronized( CONNECTIONS ) { 171 if( SSN_LIMIT != 1 ) { 172 ListIterator iter = CONNECTIONS.listIterator(); 173 while( iter.hasNext() ) { 174 conn = (SmbTransport)iter.next(); 175 if( conn.matches( address, port, localAddr, localPort ) && 176 ( SSN_LIMIT == 0 || conn.sessions.size() < SSN_LIMIT )) { 177 return conn; 178 } 179 } 180 } 181 182 conn = new SmbTransport( address, port, localAddr, localPort ); 183 CONNECTIONS.add( 0, conn ); 184 } 185 186 return conn; 187 } 188 189 SmbTransport( UniAddress address, int port, InetAddress localAddr, int localPort ) { 190 this.address = address; 191 this.port = port; 192 this.localAddr = localAddr; 193 this.localPort = localPort; 194 195 sessions = new LinkedList (); 196 responseTable = new HashMap (); 197 outLock = new Object (); 198 state = ST_GROUND; 199 200 int i; 201 for( i = 0; i < MAX_MPX_COUNT; i++ ) { 202 mids[i] = new Mid(); 203 } 204 } 205 SmbTransport() { 206 } 207 208 synchronized SmbSession getSmbSession() { 209 return getSmbSession( new NtlmPasswordAuthentication( null, null, null )); 210 } 211 synchronized SmbSession getSmbSession( NtlmPasswordAuthentication auth ) { 212 SmbSession ssn; 213 214 ListIterator iter = sessions.listIterator(); 215 while( iter.hasNext() ) { 216 ssn = (SmbSession)iter.next(); 217 if( ssn.matches( auth )) { 218 ssn.auth = auth; 219 return ssn; 220 } 221 } 222 ssn = new SmbSession( address, port, localAddr, localPort, auth ); 223 ssn.transport = this; 224 sessions.add( ssn ); 225 226 return ssn; 227 } 228 boolean matches( UniAddress address, int port, InetAddress localAddr, int localPort ) { 229 InetAddress defaultLocal = null; 230 try { 231 defaultLocal = InetAddress.getLocalHost(); 232 } catch( UnknownHostException uhe ) { 233 } 234 int p1 = ( port == 0 || port == 139 ) ? 0 : port; 235 int p2 = ( this.port == 0 || this.port == 139 ) ? 0 : this.port; 236 InetAddress la1 = localAddr == null ? defaultLocal : localAddr; 237 InetAddress la2 = this.localAddr == null ? defaultLocal : this.localAddr; 238 return address.equals( this.address ) && 239 p1 == p2 && 240 la1.equals( la2 ) && 241 localPort == this.localPort; 242 } 243 boolean hasCapability( int cap ) throws SmbException { 244 if (state == ST_GROUND) { 245 negotiate(); 246 } 247 return (capabilities & cap) == cap; 248 } 249 boolean isSignatureSetupRequired( NtlmPasswordAuthentication auth ) { 250 return ( flags2 & ServerMessageBlock.FLAGS2_SECURITY_SIGNATURES ) != 0 && 251 digest == null && 252 auth != NtlmPasswordAuthentication.NULL && 253 NtlmPasswordAuthentication.NULL.equals( auth ) == false; 254 } 255 void ensureOpen() throws IOException { 256 if( socket == null ) { 257 Object obj; 258 NbtAddress naddr; 259 String calledName; 260 261 obj = address.getAddress(); 262 if( obj instanceof NbtAddress ) { 263 naddr = (NbtAddress)obj; 264 } else { 265 try { 266 naddr = NbtAddress.getByName( ((InetAddress )obj).getHostAddress() ); 267 } catch( UnknownHostException uhe ) { 268 naddr = null; } 270 } 271 272 calledName = address.firstCalledName(); 273 do { 274 try { 275 socket = new NbtSocket( naddr, calledName, port, localAddr, localPort ); 276 break; 277 } catch( NbtException ne ) { 278 if( ne.errorClass == NbtException.ERR_SSN_SRVC && 279 ( ne.errorCode == NbtException.CALLED_NOT_PRESENT || 280 ne.errorCode == NbtException.NOT_LISTENING_CALLED )) { 281 if( DebugFile.trace ) 282 new ErrorHandler(ne); 283 } else { 284 throw ne; 285 } 286 } 287 } while(( calledName = address.nextCalledName()) != null ); 288 289 if( calledName == null ) { 290 throw new IOException ( "Failed to establish session with " + address ); 291 } 292 293 295 if( calledName == NbtAddress.SMBSERVER_NAME ) { 296 tconHostName = address.getHostAddress(); 297 } else { 298 tconHostName = calledName; 299 } 300 301 if( TCP_NODELAY ) { 302 socket.setTcpNoDelay( true ); 303 } 304 in = new PushbackInputStream ( socket.getInputStream(), PUSHBACK_BUF_SIZE ); 305 out = socket.getOutputStream(); 306 thread = new Thread ( this, "JCIFS-SmbTransport" ); 307 thread.setDaemon( true ); 308 thread.start(); 309 } 310 } 311 void tryClose( boolean inError ) { 312 SmbSession ssn; 313 314 if( socket == null ) { 315 inError = true; 316 } 317 318 ListIterator iter = sessions.listIterator(); 319 while( iter.hasNext() ) { 320 ssn = (SmbSession)iter.next(); 321 ssn.logoff( inError ); 322 } 323 if( socket != null ) { 324 try { 325 socket.close(); 326 } catch( IOException ioe ) { 327 } 328 } 329 digest = null; 330 in = null; 331 out = null; 332 socket = null; 333 thread = null; 334 responseTable.clear(); 335 referrals.clear(); 336 sessions.clear(); 337 synchronized( CONNECTIONS ) { 338 CONNECTIONS.remove( this ); 339 } 340 state = ST_GROUND; 341 } 342 public void run() { 343 Mid mid = new Mid(); 344 int i, m, nbtlen; 345 ServerMessageBlock response; 346 347 while( thread == Thread.currentThread() ) { 348 try { 349 socket.setSoTimeout( SO_TIMEOUT ); 350 351 m = 0; 352 while( m < 4 ) { 353 if(( i = in.read() ) < 0 ) { 354 return; 355 } 356 if(( i & 0xFF ) == MAGIC[m] ) { 357 m++; 358 } else if(( i & 0xFF ) == 0xFF ) { 359 m = 1; 360 } else { 361 m = 0; 362 } 363 } 364 365 nbtlen = 4 + in.available(); 366 367 synchronized( rcv_buf ) { 368 rcv_buf[0] = (byte)0xFF; 369 rcv_buf[1] = (byte)'S'; 370 rcv_buf[2] = (byte)'M'; 371 rcv_buf[3] = (byte)'B'; 372 373 if( in.read( rcv_buf, 4, ServerMessageBlock.HEADER_LENGTH - 4 ) != 374 ( ServerMessageBlock.HEADER_LENGTH - 4 )) { 375 379 break; 380 } 381 ((PushbackInputStream )in).unread( rcv_buf, 0, ServerMessageBlock.HEADER_LENGTH ); 382 if( rcv_buf[0] != (byte)0xFF || 383 rcv_buf[1] != (byte)'S' || 384 rcv_buf[2] != (byte)'M' || 385 rcv_buf[3] != (byte)'B' ) { 386 if( DebugFile.trace ) 387 DebugFile.writeln( "bad smb header, purging session message: " + address ); 388 in.skip( in.available() ); 389 continue; 390 } 391 if(( rcv_buf[ServerMessageBlock.FLAGS_OFFSET] & 392 ServerMessageBlock.FLAGS_RESPONSE ) == 393 ServerMessageBlock.FLAGS_RESPONSE ) { 394 mid.mid = (short)(ServerMessageBlock.readInt2( rcv_buf, MID_OFFSET ) & 0xFFFF); 395 396 response = (ServerMessageBlock)responseTable.get( mid ); 397 if( response == null ) { 398 if( DebugFile.trace) { 399 DebugFile.writeln( "no handler for mid=" + mid.mid + 400 ", purging session message: " + address ); 401 } 402 in.skip( in.available() ); 403 continue; 404 } 405 synchronized( response ) { 406 response.useUnicode = useUnicode; 407 408 if( DebugFile.trace ) 409 DebugFile.writeln( "new data read from socket: " + address ); 410 411 if( response instanceof SmbComTransactionResponse ) { 412 Enumeration e = (Enumeration )response; 413 if( e.hasMoreElements() ) { 414 e.nextElement(); 415 } else { 416 if( DebugFile.trace ) 417 DebugFile.writeln( "more responses to transaction than expected" ); 418 continue; 419 } 420 if((m = response.readWireFormat( in, rcv_buf, 0 )) != nbtlen ) { 421 if( DebugFile.trace ) { 422 DebugFile.writeln( "decoded " + m + " but nbtlen=" + 423 nbtlen + ", purging session message" ); 424 } 425 in.skip( in.available() ); 426 } 427 response.received = true; 428 429 if( response.errorCode != 0 || e.hasMoreElements() == false ) { 430 ((SmbComTransactionResponse)response).hasMore = false; 431 if( digest != null ) { 432 synchronized( outLock ) { 433 digest.verify(rcv_buf, 0, response); 434 } 435 } 436 response.notify(); 437 } else { 438 ensureOpen(); 439 } 440 } else { 441 response.readWireFormat( in, rcv_buf, 0 ); 442 response.received = true; 443 444 if( digest != null ) { 445 synchronized( outLock ) { 446 digest.verify(rcv_buf, 0, response); 447 } 448 } 449 450 response.notify(); 451 } 452 } 453 } else { 454 } 456 } 457 } catch( InterruptedIOException iioe ) { 458 if( responseTable.size() == 0 ) { 459 tryClose( false ); 460 } else if( DebugFile.trace ) { 461 DebugFile.writeln( "soTimeout has occured but there are " + 462 responseTable.size() + " pending requests" ); 463 } 464 } catch( IOException ioe ) { 465 synchronized( this ) { 466 tryClose( true ); 467 } 468 if( DebugFile.trace && 469 ioe.getMessage().startsWith( "Connection reset" ) == false ) { 470 DebugFile.writeln( ioe.getMessage() + ": " + address ); 471 new ErrorHandler(ioe); 472 } 473 } 474 } 475 } 476 477 synchronized DfsReferral getDfsReferral( NtlmPasswordAuthentication auth, String path ) throws SmbException { 478 String subpath, node, host; 479 DfsReferral dr = new DfsReferral(); 480 int p, n, i, s; 481 UniAddress addr; 482 483 SmbTree ipc = getSmbSession( auth ).getSmbTree( "IPC$", null ); 484 Trans2GetDfsReferralResponse resp = new Trans2GetDfsReferralResponse(); 485 ipc.sendTransaction( new Trans2GetDfsReferral( path ), resp ); 486 487 subpath = path.substring( 0, resp.pathConsumed ); 488 node = resp.referral.node; 489 if( subpath.charAt( 0 ) != '\\' || 490 (i = subpath.indexOf( '\\', 1 )) < 2 || 491 (p = subpath.indexOf( '\\', i + 1 )) < (i + 2) || 492 node.charAt( 0 ) != '\\' || 493 (s = node.indexOf( '\\', 1 )) < 2) { 494 throw new SmbException( "Invalid DFS path: " + path ); 495 } 496 if ((n = node.indexOf( '\\', s + 1 )) == -1) { 497 n = node.length(); 498 } 499 500 dr.path = subpath.substring( p ); 501 dr.node = node.substring( 0, n ); 502 dr.nodepath = node.substring( n ); 503 dr.server = node.substring( 1, s ); 504 dr.share = node.substring( s + 1, n ); 505 dr.resolveHashes = auth.hashesExternal; 506 508 return dr; 509 } 510 synchronized DfsReferral lookupReferral( String unc ) { 511 DfsReferral dr; 512 ListIterator iter = referrals.listIterator(); 513 int i, len; 514 515 while( iter.hasNext() ) { 516 dr = (DfsReferral)iter.next(); 517 len = dr.path.length(); 518 for( i = 0; i < len && i < unc.length(); i++ ) { 519 if( dr.path.charAt( i ) != unc.charAt( i )) { 520 break; 521 } 522 } 523 if( i == len && (len == unc.length() || unc.charAt( len ) == '\\')) { 524 return dr; 525 } 526 } 527 528 return null; 529 } 530 void send( ServerMessageBlock request, 531 ServerMessageBlock response ) throws SmbException { 532 Mid mid = null; 533 534 if (state == ST_GROUND) { 535 negotiate(); 536 } 537 538 request.flags2 |= flags2; 539 request.useUnicode = useUnicode; 540 541 if( response == null ) { 542 try { 543 synchronized( outLock ) { 544 mid = aquireMid(); 545 request.mid = mid.mid; 546 ensureOpen(); 547 synchronized( snd_buf ) { 548 request.digest = digest; 549 request.response = null; 550 int length = request.writeWireFormat(snd_buf, 4); 551 out.write(snd_buf, 4, length); 552 out.flush(); 553 } 554 } 555 } catch( IOException ioe ) { 556 tryClose( true ); 557 throw new SmbException( "An error occured sending the request.", ioe ); 558 } finally { 559 synchronized( outLock ) { 560 releaseMid( mid ); 561 } 562 } 563 564 return; 565 } 566 567 569 try { 570 synchronized( response ) { 571 synchronized( outLock ) { 572 response.received = false; 573 mid = aquireMid(); 574 request.mid = mid.mid; 575 responseTable.put( mid, response ); 576 ensureOpen(); 577 synchronized( snd_buf ) { 578 if( digest != null ) { 579 request.digest = digest; 580 request.response = response; 581 } 582 int length = request.writeWireFormat(snd_buf, 4); 583 out.write(snd_buf, 4, length); 584 out.flush(); 585 } 586 } 587 588 response.wait( response.responseTimeout == 1 ? RESPONSE_TIMEOUT : response.responseTimeout ); 590 } 591 } catch( InterruptedException ie ) { 592 tryClose( true ); 593 } catch( IOException ioe ) { 594 tryClose( true ); 595 throw new SmbException( "An error occured sending the request.", ioe ); 596 } finally { 597 synchronized( outLock ) { 598 responseTable.remove( mid ); 599 releaseMid( mid ); 600 } 601 } 602 603 if( response.received == false ) { 604 tryClose( true ); 605 throw new SmbException( "Timeout waiting for response from server: " + address ); 606 } else if( response.verifyFailed ) { 607 tryClose( true ); 608 throw new SmbException( "Unverifiable signature: " + address ); 609 } 610 response.errorCode = SmbException.getStatusByCode( response.errorCode ); 611 switch( response.errorCode ) { 612 case NtStatus.NT_STATUS_OK: 613 break; 614 case NtStatus.NT_STATUS_ACCESS_DENIED: 615 case NtStatus.NT_STATUS_WRONG_PASSWORD: 616 case NtStatus.NT_STATUS_LOGON_FAILURE: 617 case NtStatus.NT_STATUS_ACCOUNT_RESTRICTION: 618 case NtStatus.NT_STATUS_INVALID_LOGON_HOURS: 619 case NtStatus.NT_STATUS_INVALID_WORKSTATION: 620 case NtStatus.NT_STATUS_PASSWORD_EXPIRED: 621 case NtStatus.NT_STATUS_ACCOUNT_DISABLED: 622 case NtStatus.NT_STATUS_ACCOUNT_LOCKED_OUT: 623 throw new SmbAuthException( response.errorCode ); 624 case NtStatus.NT_STATUS_PATH_NOT_COVERED: 625 if( request.auth == null ) { 626 throw new SmbException( response.errorCode, null ); 627 } 628 DfsReferral dr = getDfsReferral( request.auth, request.path ); 629 referrals.add( dr ); 630 throw dr; 631 default: 632 throw new SmbException( response.errorCode, null ); 633 } 634 } 635 void sendTransaction( SmbComTransaction request, 636 SmbComTransactionResponse response ) throws SmbException { 637 Mid mid = null; 638 639 negotiate(); 640 641 request.flags2 |= flags2; 642 request.useUnicode = useUnicode; 643 request.maxBufferSize = snd_buf_size; 644 response.received = false; 645 response.hasMore = true; 646 response.isPrimary = true; 647 648 try { 649 request.txn_buf = BufferCache.getBuffer(); 650 response.txn_buf = BufferCache.getBuffer(); 651 652 request.nextElement(); 653 if( request.hasMoreElements() ) { 654 656 SmbComBlankResponse interimResponse = new SmbComBlankResponse(); 657 658 synchronized( interimResponse ) { 659 synchronized( outLock ) { 660 mid = aquireMid(); 661 request.mid = mid.mid; 662 responseTable.put( mid, interimResponse ); 663 ensureOpen(); 664 synchronized(snd_buf) { 665 request.digest = digest; 666 request.response = response; 667 int length = request.writeWireFormat(snd_buf, 4); 668 out.write(snd_buf, 4, length); 669 out.flush(); 670 } 671 } 672 673 interimResponse.wait( RESPONSE_TIMEOUT ); 674 675 if( interimResponse.received == false ) { 676 throw new SmbException( "Timeout waiting for response from server: " + address ); 677 } 678 interimResponse.errorCode = SmbException.getStatusByCode( interimResponse.errorCode ); 679 switch( interimResponse.errorCode ) { 680 case NtStatus.NT_STATUS_OK: 681 break; 682 case NtStatus.NT_STATUS_ACCESS_DENIED: 683 case NtStatus.NT_STATUS_WRONG_PASSWORD: 684 case NtStatus.NT_STATUS_LOGON_FAILURE: 685 case NtStatus.NT_STATUS_ACCOUNT_RESTRICTION: 686 case NtStatus.NT_STATUS_INVALID_LOGON_HOURS: 687 case NtStatus.NT_STATUS_INVALID_WORKSTATION: 688 case NtStatus.NT_STATUS_PASSWORD_EXPIRED: 689 case NtStatus.NT_STATUS_ACCOUNT_DISABLED: 690 case NtStatus.NT_STATUS_ACCOUNT_LOCKED_OUT: 691 throw new SmbAuthException( interimResponse.errorCode ); 692 case NtStatus.NT_STATUS_PATH_NOT_COVERED: 693 if( request.auth == null ) { 694 throw new SmbException( interimResponse.errorCode, null ); 695 } 696 DfsReferral dr = getDfsReferral( request.auth, request.path ); 697 referrals.add( dr ); 698 throw dr; 699 default: 700 throw new SmbException( interimResponse.errorCode, null ); 701 } 702 } 703 request.nextElement(); 704 } 705 706 synchronized( response ) { 707 synchronized( outLock ) { 708 mid = aquireMid(); 709 request.mid = mid.mid; 710 responseTable.put( mid, response ); 711 } 712 do { 713 synchronized( outLock ) { 714 ensureOpen(); 715 synchronized( snd_buf ) { 716 request.digest = digest; 717 request.response = response; 718 int length = request.writeWireFormat(snd_buf, 4); 719 out.write(snd_buf, 4, length); 720 out.flush(); 721 } 722 } 723 } while( request.hasMoreElements() && request.nextElement() != null ); 724 725 do { 726 response.received = false; 728 response.wait( response.responseTimeout == 1 ? RESPONSE_TIMEOUT : response.responseTimeout ); 729 } while( response.received && response.hasMoreElements() ); 730 } 731 } catch( InterruptedException ie ) { 732 tryClose( true ); 733 } catch( IOException ioe ) { 734 tryClose( true ); 735 throw new SmbException( "An error occured sending the request.", ioe ); 736 } finally { 737 synchronized( outLock ) { 738 responseTable.remove( mid ); 739 releaseMid( mid ); 740 } 741 BufferCache.releaseBuffer( request.txn_buf ); 742 BufferCache.releaseBuffer( response.txn_buf ); 743 } 744 745 if( response.received == false ) { 746 tryClose( true ); 747 throw new SmbException( "Timeout waiting for response from server: " + address ); 748 } else if( response.verifyFailed ) { 749 tryClose( true ); 750 throw new SmbException( "Unverifiable signature: " + address ); 751 } 752 response.errorCode = SmbException.getStatusByCode( response.errorCode ); 753 switch( response.errorCode ) { 754 case NtStatus.NT_STATUS_OK: 755 break; 756 case NtStatus.NT_STATUS_ACCESS_DENIED: 757 case NtStatus.NT_STATUS_WRONG_PASSWORD: 758 case NtStatus.NT_STATUS_LOGON_FAILURE: 759 case NtStatus.NT_STATUS_ACCOUNT_RESTRICTION: 760 case NtStatus.NT_STATUS_INVALID_LOGON_HOURS: 761 case NtStatus.NT_STATUS_INVALID_WORKSTATION: 762 case NtStatus.NT_STATUS_PASSWORD_EXPIRED: 763 case NtStatus.NT_STATUS_ACCOUNT_DISABLED: 764 case NtStatus.NT_STATUS_ACCOUNT_LOCKED_OUT: 765 throw new SmbAuthException( response.errorCode ); 766 case NtStatus.NT_STATUS_PATH_NOT_COVERED: 767 if( request.auth == null ) { 768 throw new SmbException( response.errorCode, null ); 769 } 770 DfsReferral dr = getDfsReferral( request.auth, request.path ); 771 referrals.add( dr ); 772 throw dr; 773 default: 774 throw new SmbException( response.errorCode, null ); 775 } 776 } 777 synchronized void negotiate() throws SmbException { 778 779 if( this == NULL_TRANSPORT ) { 780 throw new RuntimeException ( "Null transport cannot be used" ); 781 } 782 if( state >= ST_NEGOTIATING ) { 783 return; 784 } 785 state = ST_NEGOTIATING; 786 787 if( DebugFile.trace ) 788 DebugFile.writeln( "requesting negotiation with " + address ); 789 790 793 794 SmbComNegotiateResponse response = new SmbComNegotiateResponse(); 795 send( new SmbComNegotiate(), response ); 796 797 if( response.dialectIndex > 10 ) { 798 tryClose( true ); 799 throw new SmbException( "This client does not support the negotiated dialect." ); 800 } 801 802 server = new ServerData(); 803 server.securityMode = response.securityMode; 804 server.security = response.security; 805 server.encryptedPasswords = response.encryptedPasswords; 806 server.signaturesEnabled = response.signaturesEnabled; 807 server.signaturesRequired = response.signaturesRequired; 808 server.maxMpxCount = response.maxMpxCount; 809 server.maxNumberVcs = response.maxNumberVcs; 810 server.maxBufferSize = response.maxBufferSize; 811 server.maxRawSize = response.maxRawSize; 812 server.sessionKey = response.sessionKey; 813 server.capabilities = response.capabilities; 814 server.serverTime = response.serverTime; 815 server.serverTimeZone = response.serverTimeZone; 816 server.encryptionKeyLength = response.encryptionKeyLength; 817 server.encryptionKey = response.encryptionKey; 818 server.oemDomainName = response.oemDomainName; 819 820 if (server.signaturesRequired || (server.signaturesEnabled && SIGNPREF)) { 821 flags2 |= ServerMessageBlock.FLAGS2_SECURITY_SIGNATURES; 822 } else { 823 flags2 &= 0xFFFF ^ ServerMessageBlock.FLAGS2_SECURITY_SIGNATURES; 824 } 825 826 maxMpxCount = maxMpxCount < server.maxMpxCount ? maxMpxCount : server.maxMpxCount; 827 maxMpxCount = maxMpxCount < 1 ? 1 : maxMpxCount; 828 829 snd_buf_size = snd_buf_size < server.maxBufferSize ? snd_buf_size : server.maxBufferSize; 830 831 capabilities &= server.capabilities; 832 if(( capabilities & ServerMessageBlock.CAP_UNICODE ) == 0 ) { 833 if( FORCE_UNICODE ) { 835 capabilities |= ServerMessageBlock.CAP_UNICODE; 836 } else { 837 useUnicode = false; 838 flags2 &= 0xFFFF ^ ServerMessageBlock.FLAGS2_UNICODE; 839 } 840 } 841 } 842 public String toString() { 843 String ret = "SmbTransport[address=" + address; 844 if( socket == null ) { 845 ret += ",port=,localAddr=,localPort=]"; 846 } else { 847 ret += ",port=" + socket.getPort() + 848 ",localAddr=" + socket.getLocalAddress() + 849 ",localPort=" + socket.getLocalPort() + "]"; 850 } 851 return ret; 852 } 853 854 855 856 Mid aquireMid() throws SmbException { 857 int i; 858 859 if( mid_next == 0 ) { 860 mid_next++; 861 } 862 863 for( ;; ) { 864 for( i = 0; i < maxMpxCount; i++ ) { 865 if( mids[i].mid == 0 ) { 866 break; 867 } 868 } 869 if( i == maxMpxCount ) { 870 try { 871 outLock.wait(); 872 } catch( InterruptedException ie ) { 873 throw new SmbException( "Interrupted aquiring mid", ie ); 874 } 875 } else { 876 break; 877 } 878 } 879 880 mids[i].mid = mid_next++; 881 882 return mids[i]; 883 } 884 void releaseMid( Mid mid ) { 885 int i; 886 887 for( i = 0; i < maxMpxCount; i++ ) { 888 if( mids[i].mid == mid.mid ) { 889 mid.mid = 0; 890 outLock.notify(); 891 return; 892 } 893 } 894 if( DebugFile.trace ) 895 DebugFile.writeln( "mid not found" ); 896 } 897 } 898 | Popular Tags |