1 18 19 package com.knowgate.jcifs.smb; 20 21 import java.io.InputStream ; 22 import java.io.PushbackInputStream ; 23 import java.io.IOException ; 24 import java.io.UnsupportedEncodingException ; 25 import java.util.TimeZone ; 26 import java.util.Calendar ; 27 import java.util.Date ; 28 29 import com.knowgate.debug.*; 30 import com.knowgate.misc.Gadgets; 31 import com.knowgate.jcifs.Config; 32 33 abstract class ServerMessageBlock { 34 35 static final int FLAGS_NONE = 0x00; 36 static final int FLAGS_LOCK_AND_READ_WRITE_AND_UNLOCK = 0x01; 37 static final int FLAGS_RECEIVE_BUFFER_POSTED = 0x02; 38 static final int FLAGS_PATH_NAMES_CASELESS = 0x08; 39 static final int FLAGS_PATH_NAMES_CANONICALIZED = 0x10; 40 static final int FLAGS_OPLOCK_REQUESTED_OR_GRANTED = 0x20; 41 static final int FLAGS_NOTIFY_OF_MODIFY_ACTION = 0x40; 42 static final int FLAGS_RESPONSE = 0x80; 43 44 static final int FLAGS2_NONE = 0x0000; 45 static final int FLAGS2_LONG_FILENAMES = 0x0001; 46 static final int FLAGS2_EXTENDED_ATTRIBUTES = 0x0002; 47 static final int FLAGS2_SECURITY_SIGNATURES = 0x0004; 48 static final int FLAGS2_EXTENDED_SECURITY_NEGOTIATION = 0x0800; 49 static final int FLAGS2_RESOLVE_PATHS_IN_DFS = 0x1000; 50 static final int FLAGS2_PERMIT_READ_IF_EXECUTE_PERM = 0x2000; 51 static final int FLAGS2_STATUS32 = 0x4000; 52 static final int FLAGS2_UNICODE = 0x8000; 53 54 static final int CAP_NONE = 0x0000; 55 static final int CAP_RAW_MODE = 0x0001; 56 static final int CAP_MPX_MODE = 0x0002; 57 static final int CAP_UNICODE = 0x0004; 58 static final int CAP_LARGE_FILES = 0x0008; 59 static final int CAP_NT_SMBS = 0x0010; 60 static final int CAP_RPC_REMOTE_APIS = 0x0020; 61 static final int CAP_STATUS32 = 0x0040; 62 static final int CAP_LEVEL_II_OPLOCKS = 0x0080; 63 static final int CAP_LOCK_AND_READ = 0x0100; 64 static final int CAP_NT_FIND = 0x0200; 65 static final int CAP_DFS = 0x1000; 66 67 static final int ATTR_READONLY = 0x01; 69 static final int ATTR_HIDDEN = 0x02; 70 static final int ATTR_SYSTEM = 0x04; 71 static final int ATTR_VOLUME = 0x08; 72 static final int ATTR_DIRECTORY = 0x10; 73 static final int ATTR_ARCHIVE = 0x20; 74 75 static final int ATTR_COMPRESSED = 0x800; 77 static final int ATTR_NORMAL = 0x080; 78 static final int ATTR_TEMPORARY = 0x100; 79 80 static final int FLAGS_TARGET_MUST_BE_FILE = 0x0001; 82 static final int FLAGS_TARGET_MUST_BE_DIRECTORY = 0x0002; 83 static final int FLAGS_COPY_TARGET_MODE_ASCII = 0x0004; 84 static final int FLAGS_COPY_SOURCE_MODE_ASCII = 0x0008; 85 static final int FLAGS_VERIFY_ALL_WRITES = 0x0010; 86 static final int FLAGS_TREE_COPY = 0x0020; 87 88 static final int OPEN_FUNCTION_FAIL_IF_EXISTS = 0x0000; 90 static final int OPEN_FUNCTION_OVERWRITE_IF_EXISTS = 0x0020; 91 92 static final int PID = (int)( Math.random() * 65536d ); 93 94 static final int SECURITY_SHARE = 0x00; 95 static final int SECURITY_USER = 0x01; 96 97 static final int CMD_OFFSET = 4; 98 static final int ERROR_CODE_OFFSET = 5; 99 static final int FLAGS_OFFSET = 9; 100 static final int SIGNATURE_OFFSET = 14; 101 static final int TID_OFFSET = 24; 102 static final int HEADER_LENGTH = 32; 103 104 static final long MILLISECONDS_BETWEEN_1970_AND_1601 = 11644473600000L; 105 static final TimeZone TZ = TimeZone.getDefault(); 106 107 static final boolean USE_BATCHING = Config.getBoolean( "jcifs.smb.client.useBatching", true ); 108 static final String OEM_ENCODING = 109 Config.getProperty( "jcifs.encoding", 110 System.getProperty( "file.encoding" )); 111 112 static final byte[] header = { 113 (byte)0xFF, (byte)'S', (byte)'M', (byte)'B', 114 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, 115 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, 116 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, 117 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, 118 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 119 }; 120 121 static void writeInt2( long val, byte[] dst, int dstIndex ) { 122 dst[dstIndex] = (byte)(val); 123 dst[++dstIndex] = (byte)(val >> 8); 124 } 125 static void writeInt4( long val, byte[] dst, int dstIndex ) { 126 dst[dstIndex] = (byte)(val); 127 dst[++dstIndex] = (byte)(val >>= 8); 128 dst[++dstIndex] = (byte)(val >>= 8); 129 dst[++dstIndex] = (byte)(val >> 8); 130 } 131 static int readInt2( byte[] src, int srcIndex ) { 132 return ( src[srcIndex] & 0xFF ) + 133 (( src[srcIndex + 1] & 0xFF ) << 8 ); 134 } 135 static int readInt4( byte[] src, int srcIndex ) { 136 return ( src[srcIndex] & 0xFF ) + 137 (( src[srcIndex + 1] & 0xFF ) << 8 ) + 138 (( src[srcIndex + 2] & 0xFF ) << 16 ) + 139 (( src[srcIndex + 3] & 0xFF ) << 24 ); 140 } 141 static long readInt8( byte[] src, int srcIndex ) { 142 return (readInt4( src, srcIndex ) & 0xFFFFFFFFL) + 143 ((long)(readInt4( src, srcIndex + 4 )) << 32); 144 } 145 static void writeInt8( long val, byte[] dst, int dstIndex ) { 146 dst[dstIndex] = (byte)(val); 147 dst[++dstIndex] = (byte)(val >>= 8); 148 dst[++dstIndex] = (byte)(val >>= 8); 149 dst[++dstIndex] = (byte)(val >>= 8); 150 dst[++dstIndex] = (byte)(val >>= 8); 151 dst[++dstIndex] = (byte)(val >>= 8); 152 dst[++dstIndex] = (byte)(val >>= 8); 153 dst[++dstIndex] = (byte)(val >> 8); 154 } 155 static long readTime( byte[] src, int srcIndex ) { 156 int low = readInt4( src, srcIndex ); 157 int hi = readInt4( src, srcIndex + 4 ); 158 long t = ((long)hi << 32L ) | (low & 0xFFFFFFFFL); 159 t = ( t / 10000L - MILLISECONDS_BETWEEN_1970_AND_1601 ); 160 161 182 return t; 183 } 184 static void writeTime( long t, byte[] dst, int dstIndex ) { 185 186 if( t != 0L ) { 187 208 t = (t + MILLISECONDS_BETWEEN_1970_AND_1601) * 10000L; 209 } 210 211 writeInt8( t, dst, dstIndex ); 212 } 213 static long readUTime( byte[] buffer, int bufferIndex ) { 214 return readInt4( buffer, bufferIndex ) * 1000L; 215 } 216 static void writeUTime( long t, byte[] dst, int dstIndex ) { 217 if( t == 0L || t == 0xFFFFFFFFFFFFFFFFL ) { 218 writeInt4( 0xFFFFFFFF, dst, dstIndex ); 219 return; 220 } 221 synchronized( TZ ) { 222 if( TZ.inDaylightTime( new Date () )) { 223 if( TZ.inDaylightTime( new Date ( t ))) { 225 } else { 227 t -= 3600000; 229 } 230 } else { 231 if( TZ.inDaylightTime( new Date ( t ))) { 233 t += 3600000; 235 } else { 236 } 238 } 239 } 240 writeInt4( (int)(t / 1000L), dst, dstIndex ); 241 } 242 243 244 253 254 static final byte SMB_COM_CREATE_DIRECTORY = (byte)0x00; 255 static final byte SMB_COM_DELETE_DIRECTORY = (byte)0x01; 256 static final byte SMB_COM_CLOSE = (byte)0x04; 257 static final byte SMB_COM_DELETE = (byte)0x06; 258 static final byte SMB_COM_RENAME = (byte)0x07; 259 static final byte SMB_COM_QUERY_INFORMATION = (byte)0x08; 260 static final byte SMB_COM_WRITE = (byte)0x0B; 261 static final byte SMB_COM_CHECK_DIRECTORY = (byte)0x10; 262 static final byte SMB_COM_TRANSACTION = (byte)0x25; 263 static final byte SMB_COM_TRANSACTION_SECONDARY = (byte)0x26; 264 static final byte SMB_COM_MOVE = (byte)0x2A; 265 static final byte SMB_COM_ECHO = (byte)0x2B; 266 static final byte SMB_COM_OPEN_ANDX = (byte)0x2D; 267 static final byte SMB_COM_READ_ANDX = (byte)0x2E; 268 static final byte SMB_COM_WRITE_ANDX = (byte)0x2F; 269 static final byte SMB_COM_TRANSACTION2 = (byte)0x32; 270 static final byte SMB_COM_FIND_CLOSE2 = (byte)0x34; 271 static final byte SMB_COM_TREE_DISCONNECT = (byte)0x71; 272 static final byte SMB_COM_NEGOTIATE = (byte)0x72; 273 static final byte SMB_COM_SESSION_SETUP_ANDX = (byte)0x73; 274 static final byte SMB_COM_LOGOFF_ANDX = (byte)0x74; 275 static final byte SMB_COM_TREE_CONNECT_ANDX = (byte)0x75; 276 static final byte SMB_COM_NT_CREATE_ANDX = (byte)0xA2; 277 278 290 291 byte command, flags; 292 int headerStart, 293 length, 294 batchLevel, 295 errorCode, 296 flags2, 297 tid, pid, uid, mid, 298 wordCount, byteCount; 299 boolean useUnicode, received; 300 long responseTimeout = 1; 301 int signSeq; 302 boolean verifyFailed; 303 NtlmPasswordAuthentication auth = null; 304 String path; 305 SigningDigest digest = null; 306 ServerMessageBlock response; 307 308 ServerMessageBlock() { 309 flags = (byte)( FLAGS_PATH_NAMES_CASELESS | FLAGS_PATH_NAMES_CANONICALIZED ); 310 pid = PID; 311 batchLevel = 0; 312 } 313 314 int writeString( String str, byte[] dst, int dstIndex ) { 315 return writeString( str, dst, dstIndex, useUnicode ); 316 } 317 int writeString( String str, byte[] dst, int dstIndex, boolean useUnicode ) { 318 int start = dstIndex; 319 320 try { 321 if( useUnicode ) { 322 if((( dstIndex - headerStart ) % 2 ) != 0 ) { 324 dst[dstIndex++] = (byte)'\0'; 325 } 326 System.arraycopy( str.getBytes( "UnicodeLittleUnmarked" ), 0, 327 dst, dstIndex, str.length() * 2 ); 328 dstIndex += str.length() * 2; 329 dst[dstIndex++] = (byte)'\0'; 330 dst[dstIndex++] = (byte)'\0'; 331 } else { 332 byte[] b = str.getBytes( OEM_ENCODING ); 333 System.arraycopy( b, 0, dst, dstIndex, b.length ); 334 dstIndex += b.length; 335 dst[dstIndex++] = (byte)'\0'; 336 } 337 } catch( UnsupportedEncodingException uee ) { 338 if( DebugFile.trace ) 339 new ErrorHandler(uee); 340 } 341 342 return dstIndex - start; 343 } 344 String readString( byte[] src, int srcIndex ) { 345 return readString( src, srcIndex, 256, useUnicode ); 346 } 347 String readString( byte[] src, int srcIndex, int maxLen, boolean useUnicode ) { 348 int len = 0; 349 String str = null; 350 try { 351 if( useUnicode ) { 352 if((( srcIndex - headerStart ) % 2 ) != 0 ) { 354 srcIndex++; 355 } 356 while( src[srcIndex + len] != (byte)0x00 || 357 src[srcIndex + len + 1] != (byte)0x00 ) { 358 len += 2; 359 if( len > maxLen ) { 360 throw new RuntimeException ( "zero termination not found" ); 361 } 362 } 363 str = new String ( src, srcIndex, len, "UnicodeLittle" ); 364 } else { 365 while( src[srcIndex + len] != (byte)0x00 ) { 366 len++; 367 if( len > maxLen ) { 368 throw new RuntimeException ( "zero termination not found" ); 369 } 370 } 371 str = new String ( src, srcIndex, len, OEM_ENCODING ); 372 } 373 } catch( UnsupportedEncodingException uee ) { 374 if( DebugFile.trace ) 375 new ErrorHandler(uee); 376 } 377 return str; 378 } 379 int stringWireLength( String str, int offset ) { 380 int len = str.length() + 1; 381 if( useUnicode ) { 382 len = str.length() * 2 + 2; 383 len = ( offset % 2 ) != 0 ? len + 1 : len; 384 } 385 return len; 386 } 387 int readStringLength( byte[] src, int srcIndex, int max ) { 388 int len = 0; 389 while( src[srcIndex + len] != (byte)0x00 ) { 390 if( len++ > max ) { 391 throw new RuntimeException ( "zero termination not found: " + this ); 392 } 393 } 394 return len; 395 } 396 int writeWireFormat( byte[] dst, int dstIndex ) { 397 int start = headerStart = dstIndex; 398 399 dstIndex += writeHeaderWireFormat( dst, dstIndex ); 400 wordCount = writeParameterWordsWireFormat( dst, dstIndex + 1 ); 401 dst[dstIndex++] = (byte)(( wordCount / 2 ) & 0xFF ); 402 dstIndex += wordCount; 403 wordCount /= 2; 404 byteCount = writeBytesWireFormat( dst, dstIndex + 2 ); 405 dst[dstIndex++] = (byte)( byteCount & 0xFF ); 406 dst[dstIndex++] = (byte)(( byteCount >> 8 ) & 0xFF ); 407 dstIndex += byteCount; 408 409 length = dstIndex - start; 410 411 if( digest != null ) { 412 digest.sign( dst, headerStart, length, this, response ); 413 } 414 415 return length; 416 } 417 int readWireFormat( InputStream in, 418 byte[] buffer, 419 int bufferIndex ) 420 throws IOException { 421 422 int start = headerStart = bufferIndex; 423 424 427 428 if( in.read( buffer, bufferIndex, HEADER_LENGTH ) != HEADER_LENGTH ) { 429 throw new IOException ( "unexpected EOF reading smb header" ); 430 } 431 bufferIndex += readHeaderWireFormat( buffer, bufferIndex ); 432 433 436 437 if(( wordCount = in.read() ) == -1 ) { 438 throw new IOException ( "unexpected EOF reading smb wordCount" ); 439 } 440 buffer[bufferIndex++] = (byte)( wordCount & 0xFF ); 441 442 445 446 if( wordCount != 0 ) { 447 if( in.read( buffer, bufferIndex, wordCount * 2 ) != wordCount * 2 ) { 448 throw new IOException ( "unexpected EOF reading smb parameter words" ); 449 } 450 int n; 451 if(( n = readParameterWordsWireFormat( buffer, bufferIndex )) != wordCount * 2 ) { 452 if( DebugFile.trace ) { 453 DebugFile.writeln( "wordCount * 2=" + ( wordCount * 2 ) + 454 " but readParameterWordsWireFormat returned " + n ); 455 } 456 } 457 bufferIndex += wordCount * 2; 458 } 459 460 463 464 if( in.read( buffer, bufferIndex, 2 ) != 2 ) { 465 throw new IOException ( "unexpected EOF reading smb byteCount" ); 466 } 467 byteCount = readInt2( buffer, bufferIndex ); 468 bufferIndex += 2; 469 470 473 474 if( byteCount != 0 ) { 475 if( in.read( buffer, bufferIndex, byteCount ) != byteCount ) { 476 throw new IOException ( "unexpected EOF reading smb" ); 477 } 478 int n; 479 if(( n = readBytesWireFormat( buffer, bufferIndex )) != byteCount ) { 480 if( DebugFile.trace ) { 481 DebugFile.writeln( "byteCount=" + byteCount + 482 " but readBytesWireFormat returned " + n ); 483 } 484 } 485 488 bufferIndex += byteCount; 489 } 490 491 length = bufferIndex - start; 492 return length; 493 } 494 int writeHeaderWireFormat( byte[] dst, int dstIndex ) { 495 System.arraycopy( header, 0, dst, dstIndex, header.length ); 496 dst[dstIndex + CMD_OFFSET] = command; 497 dst[dstIndex + FLAGS_OFFSET] = flags; 498 writeInt2( flags2, dst, dstIndex + FLAGS_OFFSET + 1 ); 499 dstIndex += TID_OFFSET; 500 writeInt2( tid, dst, dstIndex ); 501 writeInt2( pid, dst, dstIndex + 2 ); 502 writeInt2( uid, dst, dstIndex + 4 ); 503 writeInt2( mid, dst, dstIndex + 6 ); 504 return HEADER_LENGTH; 505 } 506 int readHeaderWireFormat( byte[] buffer, int bufferIndex ) throws IOException { 507 command = buffer[bufferIndex + CMD_OFFSET]; 508 errorCode = readInt4( buffer, bufferIndex + ERROR_CODE_OFFSET ); 509 flags = buffer[bufferIndex + FLAGS_OFFSET]; 510 flags2 = readInt2( buffer, bufferIndex + FLAGS_OFFSET + 1 ); 511 tid = readInt2( buffer, bufferIndex + TID_OFFSET ); 512 pid = readInt2( buffer, bufferIndex + TID_OFFSET + 2 ); 513 uid = readInt2( buffer, bufferIndex + TID_OFFSET + 4 ); 514 mid = readInt2( buffer, bufferIndex + TID_OFFSET + 6 ); 515 return HEADER_LENGTH; 516 } 517 boolean isResponse() { 518 return ( flags & FLAGS_RESPONSE ) == FLAGS_RESPONSE; 519 } 520 521 541 542 abstract int writeParameterWordsWireFormat( byte[] dst, int dstIndex ); 543 abstract int writeBytesWireFormat( byte[] dst, int dstIndex ); 544 abstract int readParameterWordsWireFormat( byte[] buffer, 545 int bufferIndex ) 546 throws IOException ; 547 abstract int readBytesWireFormat( byte[] buffer, 548 int bufferIndex ) 549 throws IOException ; 550 551 public String toString() { 552 String c; 553 switch( command ) { 554 case SMB_COM_NEGOTIATE: 555 c = "SMB_COM_NEGOTIATE"; 556 break; 557 case SMB_COM_SESSION_SETUP_ANDX: 558 c = "SMB_COM_SESSION_SETUP_ANDX"; 559 break; 560 case SMB_COM_TREE_CONNECT_ANDX: 561 c = "SMB_COM_TREE_CONNECT_ANDX"; 562 break; 563 case SMB_COM_QUERY_INFORMATION: 564 c = "SMB_COM_QUERY_INFORMATION"; 565 break; 566 case SMB_COM_CHECK_DIRECTORY: 567 c = "SMB_COM_CHECK_DIRECTORY"; 568 break; 569 case SMB_COM_TRANSACTION: 570 c = "SMB_COM_TRANSACTION"; 571 break; 572 case SMB_COM_TRANSACTION2: 573 c = "SMB_COM_TRANSACTION2"; 574 break; 575 case SMB_COM_TRANSACTION_SECONDARY: 576 c = "SMB_COM_TRANSACTION_SECONDARY"; 577 break; 578 case SMB_COM_FIND_CLOSE2: 579 c = "SMB_COM_FIND_CLOSE2"; 580 break; 581 case SMB_COM_TREE_DISCONNECT: 582 c = "SMB_COM_TREE_DISCONNECT"; 583 break; 584 case SMB_COM_LOGOFF_ANDX: 585 c = "SMB_COM_LOGOFF_ANDX"; 586 break; 587 case SMB_COM_ECHO: 588 c = "SMB_COM_ECHO"; 589 break; 590 case SMB_COM_MOVE: 591 c = "SMB_COM_MOVE"; 592 break; 593 case SMB_COM_RENAME: 594 c = "SMB_COM_RENAME"; 595 break; 596 case SMB_COM_DELETE: 597 c = "SMB_COM_DELETE"; 598 break; 599 case SMB_COM_DELETE_DIRECTORY: 600 c = "SMB_COM_DELETE_DIRECTORY"; 601 break; 602 case SMB_COM_NT_CREATE_ANDX: 603 c = "SMB_COM_NT_CREATE_ANDX"; 604 break; 605 case SMB_COM_OPEN_ANDX: 606 c = "SMB_COM_OPEN_ANDX"; 607 break; 608 case SMB_COM_READ_ANDX: 609 c = "SMB_COM_READ_ANDX"; 610 break; 611 case SMB_COM_CLOSE: 612 c = "SMB_COM_CLOSE"; 613 break; 614 case SMB_COM_WRITE_ANDX: 615 c = "SMB_COM_WRITE_ANDX"; 616 break; 617 case SMB_COM_CREATE_DIRECTORY: 618 c = "SMB_COM_CREATE_DIRECTORY"; 619 break; 620 default: 621 c = "UNKNOWN"; 622 } 623 return new String ( 624 "command=" + c + 625 ",received=" + received + 626 ",errorCode=" + SmbException.getMessageByCode( errorCode ) + 627 ",flags=0x" + Gadgets.toHexString( flags & 0xFF, 4 ) + 628 ",flags2=0x" + Gadgets.toHexString( flags2, 4 ) + 629 ",signSeq=" + signSeq + 630 ",tid=" + tid + 631 ",pid=" + pid + 632 ",uid=" + uid + 633 ",mid=" + mid + 634 ",wordCount=" + wordCount + 635 ",byteCount=" + byteCount ); 636 } 637 } 638 | Popular Tags |