001: /* jcifs smb client library in Java
002: * Copyright (C) 2000 "Michael B. Allen" <jcifs at samba dot org>
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2.1 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018:
019: package com.knowgate.jcifs.smb;
020:
021: import java.io.InputStream;
022: import java.io.PushbackInputStream;
023: import java.io.IOException;
024: import java.io.UnsupportedEncodingException;
025: import java.util.TimeZone;
026: import java.util.Calendar;
027: import java.util.Date;
028:
029: import com.knowgate.debug.*;
030: import com.knowgate.misc.Gadgets;
031: import com.knowgate.jcifs.Config;
032:
033: abstract class ServerMessageBlock {
034:
035: static final int FLAGS_NONE = 0x00;
036: static final int FLAGS_LOCK_AND_READ_WRITE_AND_UNLOCK = 0x01;
037: static final int FLAGS_RECEIVE_BUFFER_POSTED = 0x02;
038: static final int FLAGS_PATH_NAMES_CASELESS = 0x08;
039: static final int FLAGS_PATH_NAMES_CANONICALIZED = 0x10;
040: static final int FLAGS_OPLOCK_REQUESTED_OR_GRANTED = 0x20;
041: static final int FLAGS_NOTIFY_OF_MODIFY_ACTION = 0x40;
042: static final int FLAGS_RESPONSE = 0x80;
043:
044: static final int FLAGS2_NONE = 0x0000;
045: static final int FLAGS2_LONG_FILENAMES = 0x0001;
046: static final int FLAGS2_EXTENDED_ATTRIBUTES = 0x0002;
047: static final int FLAGS2_SECURITY_SIGNATURES = 0x0004;
048: static final int FLAGS2_EXTENDED_SECURITY_NEGOTIATION = 0x0800;
049: static final int FLAGS2_RESOLVE_PATHS_IN_DFS = 0x1000;
050: static final int FLAGS2_PERMIT_READ_IF_EXECUTE_PERM = 0x2000;
051: static final int FLAGS2_STATUS32 = 0x4000;
052: static final int FLAGS2_UNICODE = 0x8000;
053:
054: static final int CAP_NONE = 0x0000;
055: static final int CAP_RAW_MODE = 0x0001;
056: static final int CAP_MPX_MODE = 0x0002;
057: static final int CAP_UNICODE = 0x0004;
058: static final int CAP_LARGE_FILES = 0x0008;
059: static final int CAP_NT_SMBS = 0x0010;
060: static final int CAP_RPC_REMOTE_APIS = 0x0020;
061: static final int CAP_STATUS32 = 0x0040;
062: static final int CAP_LEVEL_II_OPLOCKS = 0x0080;
063: static final int CAP_LOCK_AND_READ = 0x0100;
064: static final int CAP_NT_FIND = 0x0200;
065: static final int CAP_DFS = 0x1000;
066:
067: // file attribute encoding
068: static final int ATTR_READONLY = 0x01;
069: static final int ATTR_HIDDEN = 0x02;
070: static final int ATTR_SYSTEM = 0x04;
071: static final int ATTR_VOLUME = 0x08;
072: static final int ATTR_DIRECTORY = 0x10;
073: static final int ATTR_ARCHIVE = 0x20;
074:
075: // extended file attribute encoding(others same as above)
076: static final int ATTR_COMPRESSED = 0x800;
077: static final int ATTR_NORMAL = 0x080;
078: static final int ATTR_TEMPORARY = 0x100;
079:
080: // flags for move and copy
081: static final int FLAGS_TARGET_MUST_BE_FILE = 0x0001;
082: static final int FLAGS_TARGET_MUST_BE_DIRECTORY = 0x0002;
083: static final int FLAGS_COPY_TARGET_MODE_ASCII = 0x0004;
084: static final int FLAGS_COPY_SOURCE_MODE_ASCII = 0x0008;
085: static final int FLAGS_VERIFY_ALL_WRITES = 0x0010;
086: static final int FLAGS_TREE_COPY = 0x0020;
087:
088: // open function
089: static final int OPEN_FUNCTION_FAIL_IF_EXISTS = 0x0000;
090: static final int OPEN_FUNCTION_OVERWRITE_IF_EXISTS = 0x0020;
091:
092: static final int PID = (int) (Math.random() * 65536d);
093:
094: static final int SECURITY_SHARE = 0x00;
095: static final int SECURITY_USER = 0x01;
096:
097: static final int CMD_OFFSET = 4;
098: static final int ERROR_CODE_OFFSET = 5;
099: 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(
108: "jcifs.smb.client.useBatching", true);
109: static final String OEM_ENCODING = Config.getProperty(
110: "jcifs.encoding", System.getProperty("file.encoding"));
111:
112: static final byte[] header = { (byte) 0xFF, (byte) 'S', (byte) 'M',
113: (byte) 'B', (byte) 0x00, (byte) 0x00, (byte) 0x00,
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 };
119:
120: static void writeInt2(long val, byte[] dst, int dstIndex) {
121: dst[dstIndex] = (byte) (val);
122: dst[++dstIndex] = (byte) (val >> 8);
123: }
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:
132: static int readInt2(byte[] src, int srcIndex) {
133: return (src[srcIndex] & 0xFF)
134: + ((src[srcIndex + 1] & 0xFF) << 8);
135: }
136:
137: static int readInt4(byte[] src, int srcIndex) {
138: return (src[srcIndex] & 0xFF)
139: + ((src[srcIndex + 1] & 0xFF) << 8)
140: + ((src[srcIndex + 2] & 0xFF) << 16)
141: + ((src[srcIndex + 3] & 0xFF) << 24);
142: }
143:
144: static long readInt8(byte[] src, int srcIndex) {
145: return (readInt4(src, srcIndex) & 0xFFFFFFFFL)
146: + ((long) (readInt4(src, srcIndex + 4)) << 32);
147: }
148:
149: static void writeInt8(long val, byte[] dst, int dstIndex) {
150: dst[dstIndex] = (byte) (val);
151: dst[++dstIndex] = (byte) (val >>= 8);
152: dst[++dstIndex] = (byte) (val >>= 8);
153: dst[++dstIndex] = (byte) (val >>= 8);
154: dst[++dstIndex] = (byte) (val >>= 8);
155: dst[++dstIndex] = (byte) (val >>= 8);
156: dst[++dstIndex] = (byte) (val >>= 8);
157: dst[++dstIndex] = (byte) (val >> 8);
158: }
159:
160: static long readTime(byte[] src, int srcIndex) {
161: int low = readInt4(src, srcIndex);
162: int hi = readInt4(src, srcIndex + 4);
163: long t = ((long) hi << 32L) | (low & 0xFFFFFFFFL);
164: t = (t / 10000L - MILLISECONDS_BETWEEN_1970_AND_1601);
165:
166: /*
167: synchronized( TZ ) {
168: if( TZ.inDaylightTime( new Date() )) {
169: // in DST
170: if( TZ.inDaylightTime( new Date( t ))) {
171: // t also in DST so no correction
172: return t;
173: }
174: // t not in DST so add 1 hour
175: return t + 3600000;
176: } else {
177: // not in DST
178: if( TZ.inDaylightTime( new Date( t ))) {
179: // t is in DST so subtract 1 hour
180: return t - 3600000;
181: }
182: // t isn't in DST either
183: return t;
184: }
185: }
186: */
187: return t;
188: }
189:
190: static void writeTime(long t, byte[] dst, int dstIndex) {
191:
192: if (t != 0L) {
193: /*
194: synchronized( TZ ) {
195: if( TZ.inDaylightTime( new Date() )) {
196: // in DST
197: if( TZ.inDaylightTime( new Date( t ))) {
198: // t also in DST so no correction
199: } else {
200: // t not in DST so subtract 1 hour
201: t -= 3600000;
202: }
203: } else {
204: // not in DST
205: if( TZ.inDaylightTime( new Date( t ))) {
206: // t is in DST so add 1 hour
207: t += 3600000;
208: } else {
209: // t isn't in DST either
210: }
211: }
212: }
213: */
214: t = (t + MILLISECONDS_BETWEEN_1970_AND_1601) * 10000L;
215: }
216:
217: writeInt8(t, dst, dstIndex);
218: }
219:
220: static long readUTime(byte[] buffer, int bufferIndex) {
221: return readInt4(buffer, bufferIndex) * 1000L;
222: }
223:
224: static void writeUTime(long t, byte[] dst, int dstIndex) {
225: if (t == 0L || t == 0xFFFFFFFFFFFFFFFFL) {
226: writeInt4(0xFFFFFFFF, dst, dstIndex);
227: return;
228: }
229: synchronized (TZ) {
230: if (TZ.inDaylightTime(new Date())) {
231: // in DST
232: if (TZ.inDaylightTime(new Date(t))) {
233: // t also in DST so no correction
234: } else {
235: // t not in DST so subtract 1 hour
236: t -= 3600000;
237: }
238: } else {
239: // not in DST
240: if (TZ.inDaylightTime(new Date(t))) {
241: // t is in DST so add 1 hour
242: t += 3600000;
243: } else {
244: // t isn't in DST either
245: }
246: }
247: }
248: writeInt4((int) (t / 1000L), dst, dstIndex);
249: }
250:
251: /*
252: * These are all the smbs supported by this library. This includes requests
253: * and well as their responses for each type however the actuall implementations
254: * of the readXxxWireFormat and writeXxxWireFormat methods may not be in
255: * place. For example at the time of this writing the readXxxWireFormat
256: * for requests and the writeXxxWireFormat for responses are not implemented
257: * and simply return 0. These would need to be completed for a server
258: * implementation.
259: */
260:
261: static final byte SMB_COM_CREATE_DIRECTORY = (byte) 0x00;
262: static final byte SMB_COM_DELETE_DIRECTORY = (byte) 0x01;
263: static final byte SMB_COM_CLOSE = (byte) 0x04;
264: static final byte SMB_COM_DELETE = (byte) 0x06;
265: static final byte SMB_COM_RENAME = (byte) 0x07;
266: static final byte SMB_COM_QUERY_INFORMATION = (byte) 0x08;
267: static final byte SMB_COM_WRITE = (byte) 0x0B;
268: static final byte SMB_COM_CHECK_DIRECTORY = (byte) 0x10;
269: static final byte SMB_COM_TRANSACTION = (byte) 0x25;
270: static final byte SMB_COM_TRANSACTION_SECONDARY = (byte) 0x26;
271: static final byte SMB_COM_MOVE = (byte) 0x2A;
272: static final byte SMB_COM_ECHO = (byte) 0x2B;
273: static final byte SMB_COM_OPEN_ANDX = (byte) 0x2D;
274: static final byte SMB_COM_READ_ANDX = (byte) 0x2E;
275: static final byte SMB_COM_WRITE_ANDX = (byte) 0x2F;
276: static final byte SMB_COM_TRANSACTION2 = (byte) 0x32;
277: static final byte SMB_COM_FIND_CLOSE2 = (byte) 0x34;
278: static final byte SMB_COM_TREE_DISCONNECT = (byte) 0x71;
279: static final byte SMB_COM_NEGOTIATE = (byte) 0x72;
280: static final byte SMB_COM_SESSION_SETUP_ANDX = (byte) 0x73;
281: static final byte SMB_COM_LOGOFF_ANDX = (byte) 0x74;
282: static final byte SMB_COM_TREE_CONNECT_ANDX = (byte) 0x75;
283: static final byte SMB_COM_NT_CREATE_ANDX = (byte) 0xA2;
284:
285: /*
286: * Some fields specify the offset from the beginning of the header. This
287: * field should be used for calculating that. This would likely be zero
288: * but an implemantation that encorporates the transport header(for
289: * efficiency) might use a different initial bufferIndex. For example,
290: * to eliminate copying data when writing NbtSession data one might
291: * manage that 4 byte header specifically and therefore the initial
292: * bufferIndex, and thus headerStart, would be 4).(NOTE: If one where
293: * looking for a way to improve perfomance this is precisly what you
294: * would want to do as the jcifs.netbios.SocketXxxputStream classes
295: * arraycopy all data read or written into a new buffer shifted over 4!)
296: */
297:
298: byte command, flags;
299: int headerStart, length, batchLevel, errorCode, flags2, tid, pid,
300: uid, mid, wordCount, byteCount;
301: boolean useUnicode, received;
302: long responseTimeout = 1;
303: int signSeq;
304: boolean verifyFailed;
305: NtlmPasswordAuthentication auth = null;
306: String path;
307: SigningDigest digest = null;
308: ServerMessageBlock response;
309:
310: ServerMessageBlock() {
311: flags = (byte) (FLAGS_PATH_NAMES_CASELESS | FLAGS_PATH_NAMES_CANONICALIZED);
312: pid = PID;
313: batchLevel = 0;
314: }
315:
316: int writeString(String str, byte[] dst, int dstIndex) {
317: return writeString(str, dst, dstIndex, useUnicode);
318: }
319:
320: int writeString(String str, byte[] dst, int dstIndex,
321: boolean useUnicode) {
322: int start = dstIndex;
323:
324: try {
325: if (useUnicode) {
326: // Unicode requires word alignment
327: if (((dstIndex - headerStart) % 2) != 0) {
328: dst[dstIndex++] = (byte) '\0';
329: }
330: System.arraycopy(str.getBytes("UnicodeLittleUnmarked"),
331: 0, dst, dstIndex, str.length() * 2);
332: dstIndex += str.length() * 2;
333: dst[dstIndex++] = (byte) '\0';
334: dst[dstIndex++] = (byte) '\0';
335: } else {
336: byte[] b = str.getBytes(OEM_ENCODING);
337: System.arraycopy(b, 0, dst, dstIndex, b.length);
338: dstIndex += b.length;
339: dst[dstIndex++] = (byte) '\0';
340: }
341: } catch (UnsupportedEncodingException uee) {
342: if (DebugFile.trace)
343: new ErrorHandler(uee);
344: }
345:
346: return dstIndex - start;
347: }
348:
349: String readString(byte[] src, int srcIndex) {
350: return readString(src, srcIndex, 256, useUnicode);
351: }
352:
353: String readString(byte[] src, int srcIndex, int maxLen,
354: boolean useUnicode) {
355: int len = 0;
356: String str = null;
357: try {
358: if (useUnicode) {
359: // Unicode requires word alignment
360: if (((srcIndex - headerStart) % 2) != 0) {
361: srcIndex++;
362: }
363: while (src[srcIndex + len] != (byte) 0x00
364: || src[srcIndex + len + 1] != (byte) 0x00) {
365: len += 2;
366: if (len > maxLen) {
367: throw new RuntimeException(
368: "zero termination not found");
369: }
370: }
371: str = new String(src, srcIndex, len, "UnicodeLittle");
372: } else {
373: while (src[srcIndex + len] != (byte) 0x00) {
374: len++;
375: if (len > maxLen) {
376: throw new RuntimeException(
377: "zero termination not found");
378: }
379: }
380: str = new String(src, srcIndex, len, OEM_ENCODING);
381: }
382: } catch (UnsupportedEncodingException uee) {
383: if (DebugFile.trace)
384: new ErrorHandler(uee);
385: }
386: return str;
387: }
388:
389: int stringWireLength(String str, int offset) {
390: int len = str.length() + 1;
391: if (useUnicode) {
392: len = str.length() * 2 + 2;
393: len = (offset % 2) != 0 ? len + 1 : len;
394: }
395: return len;
396: }
397:
398: int readStringLength(byte[] src, int srcIndex, int max) {
399: int len = 0;
400: while (src[srcIndex + len] != (byte) 0x00) {
401: if (len++ > max) {
402: throw new RuntimeException(
403: "zero termination not found: " + this );
404: }
405: }
406: return len;
407: }
408:
409: int writeWireFormat(byte[] dst, int dstIndex) {
410: int start = headerStart = dstIndex;
411:
412: dstIndex += writeHeaderWireFormat(dst, dstIndex);
413: wordCount = writeParameterWordsWireFormat(dst, dstIndex + 1);
414: dst[dstIndex++] = (byte) ((wordCount / 2) & 0xFF);
415: dstIndex += wordCount;
416: wordCount /= 2;
417: byteCount = writeBytesWireFormat(dst, dstIndex + 2);
418: dst[dstIndex++] = (byte) (byteCount & 0xFF);
419: dst[dstIndex++] = (byte) ((byteCount >> 8) & 0xFF);
420: dstIndex += byteCount;
421:
422: length = dstIndex - start;
423:
424: if (digest != null) {
425: digest.sign(dst, headerStart, length, this , response);
426: }
427:
428: return length;
429: }
430:
431: int readWireFormat(InputStream in, byte[] buffer, int bufferIndex)
432: throws IOException {
433:
434: int start = headerStart = bufferIndex;
435:
436: /*
437: * read header
438: */
439:
440: if (in.read(buffer, bufferIndex, HEADER_LENGTH) != HEADER_LENGTH) {
441: throw new IOException("unexpected EOF reading smb header");
442: }
443: bufferIndex += readHeaderWireFormat(buffer, bufferIndex);
444:
445: /*
446: * read wordCount
447: */
448:
449: if ((wordCount = in.read()) == -1) {
450: throw new IOException(
451: "unexpected EOF reading smb wordCount");
452: }
453: buffer[bufferIndex++] = (byte) (wordCount & 0xFF);
454:
455: /*
456: * read parameter words
457: */
458:
459: if (wordCount != 0) {
460: if (in.read(buffer, bufferIndex, wordCount * 2) != wordCount * 2) {
461: throw new IOException(
462: "unexpected EOF reading smb parameter words");
463: }
464: int n;
465: if ((n = readParameterWordsWireFormat(buffer, bufferIndex)) != wordCount * 2) {
466: if (DebugFile.trace) {
467: DebugFile
468: .writeln("wordCount * 2="
469: + (wordCount * 2)
470: + " but readParameterWordsWireFormat returned "
471: + n);
472: }
473: }
474: bufferIndex += wordCount * 2;
475: }
476:
477: /*
478: * read byteCount
479: */
480:
481: if (in.read(buffer, bufferIndex, 2) != 2) {
482: throw new IOException(
483: "unexpected EOF reading smb byteCount");
484: }
485: byteCount = readInt2(buffer, bufferIndex);
486: bufferIndex += 2;
487:
488: /*
489: * read bytes
490: */
491:
492: if (byteCount != 0) {
493: if (in.read(buffer, bufferIndex, byteCount) != byteCount) {
494: throw new IOException("unexpected EOF reading smb");
495: }
496: int n;
497: if ((n = readBytesWireFormat(buffer, bufferIndex)) != byteCount) {
498: if (DebugFile.trace) {
499: DebugFile.writeln("byteCount=" + byteCount
500: + " but readBytesWireFormat returned " + n);
501: }
502: }
503: // Don't think we can rely on n being correct here. Must use byteCount.
504: // Last paragraph of section 3.13.3 eludes to this.
505:
506: bufferIndex += byteCount;
507: }
508:
509: length = bufferIndex - start;
510: return length;
511: }
512:
513: int writeHeaderWireFormat(byte[] dst, int dstIndex) {
514: System.arraycopy(header, 0, dst, dstIndex, header.length);
515: dst[dstIndex + CMD_OFFSET] = command;
516: dst[dstIndex + FLAGS_OFFSET] = flags;
517: writeInt2(flags2, dst, dstIndex + FLAGS_OFFSET + 1);
518: dstIndex += TID_OFFSET;
519: writeInt2(tid, dst, dstIndex);
520: writeInt2(pid, dst, dstIndex + 2);
521: writeInt2(uid, dst, dstIndex + 4);
522: writeInt2(mid, dst, dstIndex + 6);
523: return HEADER_LENGTH;
524: }
525:
526: int readHeaderWireFormat(byte[] buffer, int bufferIndex)
527: throws IOException {
528: command = buffer[bufferIndex + CMD_OFFSET];
529: errorCode = readInt4(buffer, bufferIndex + ERROR_CODE_OFFSET);
530: flags = buffer[bufferIndex + FLAGS_OFFSET];
531: flags2 = readInt2(buffer, bufferIndex + FLAGS_OFFSET + 1);
532: tid = readInt2(buffer, bufferIndex + TID_OFFSET);
533: pid = readInt2(buffer, bufferIndex + TID_OFFSET + 2);
534: uid = readInt2(buffer, bufferIndex + TID_OFFSET + 4);
535: mid = readInt2(buffer, bufferIndex + TID_OFFSET + 6);
536: return HEADER_LENGTH;
537: }
538:
539: boolean isResponse() {
540: return (flags & FLAGS_RESPONSE) == FLAGS_RESPONSE;
541: }
542:
543: /*
544: * For this packet deconstruction technique to work for
545: * other networking protocols the InputStream may need
546: * to be passed to the readXxxWireFormat methods. This is
547: * actually purer. However, in the case of smb we know the
548: * wordCount and byteCount. And since every subclass of
549: * ServerMessageBlock would have to perform the same read
550: * operation on the input stream, we might as will pull that
551: * common functionality into the superclass and read wordCount
552: * and byteCount worth of data.
553: *
554: * We will still use the readXxxWireFormat return values to
555: * indicate how many bytes(note: readParameterWordsWireFormat
556: * returns bytes read and not the number of words(but the
557: * wordCount member DOES store the number of words)) we
558: * actually read. Incedentally this is important to the
559: * AndXServerMessageBlock class that needs to potentially
560: * read in another smb's parameter words and bytes based on
561: * information in it's andxCommand, andxOffset, ...etc.
562: */
563:
564: abstract int writeParameterWordsWireFormat(byte[] dst, int dstIndex);
565:
566: abstract int writeBytesWireFormat(byte[] dst, int dstIndex);
567:
568: abstract int readParameterWordsWireFormat(byte[] buffer,
569: int bufferIndex) throws IOException;
570:
571: abstract int readBytesWireFormat(byte[] buffer, int bufferIndex)
572: throws IOException;
573:
574: public String toString() {
575: String c;
576: switch (command) {
577: case SMB_COM_NEGOTIATE:
578: c = "SMB_COM_NEGOTIATE";
579: break;
580: case SMB_COM_SESSION_SETUP_ANDX:
581: c = "SMB_COM_SESSION_SETUP_ANDX";
582: break;
583: case SMB_COM_TREE_CONNECT_ANDX:
584: c = "SMB_COM_TREE_CONNECT_ANDX";
585: break;
586: case SMB_COM_QUERY_INFORMATION:
587: c = "SMB_COM_QUERY_INFORMATION";
588: break;
589: case SMB_COM_CHECK_DIRECTORY:
590: c = "SMB_COM_CHECK_DIRECTORY";
591: break;
592: case SMB_COM_TRANSACTION:
593: c = "SMB_COM_TRANSACTION";
594: break;
595: case SMB_COM_TRANSACTION2:
596: c = "SMB_COM_TRANSACTION2";
597: break;
598: case SMB_COM_TRANSACTION_SECONDARY:
599: c = "SMB_COM_TRANSACTION_SECONDARY";
600: break;
601: case SMB_COM_FIND_CLOSE2:
602: c = "SMB_COM_FIND_CLOSE2";
603: break;
604: case SMB_COM_TREE_DISCONNECT:
605: c = "SMB_COM_TREE_DISCONNECT";
606: break;
607: case SMB_COM_LOGOFF_ANDX:
608: c = "SMB_COM_LOGOFF_ANDX";
609: break;
610: case SMB_COM_ECHO:
611: c = "SMB_COM_ECHO";
612: break;
613: case SMB_COM_MOVE:
614: c = "SMB_COM_MOVE";
615: break;
616: case SMB_COM_RENAME:
617: c = "SMB_COM_RENAME";
618: break;
619: case SMB_COM_DELETE:
620: c = "SMB_COM_DELETE";
621: break;
622: case SMB_COM_DELETE_DIRECTORY:
623: c = "SMB_COM_DELETE_DIRECTORY";
624: break;
625: case SMB_COM_NT_CREATE_ANDX:
626: c = "SMB_COM_NT_CREATE_ANDX";
627: break;
628: case SMB_COM_OPEN_ANDX:
629: c = "SMB_COM_OPEN_ANDX";
630: break;
631: case SMB_COM_READ_ANDX:
632: c = "SMB_COM_READ_ANDX";
633: break;
634: case SMB_COM_CLOSE:
635: c = "SMB_COM_CLOSE";
636: break;
637: case SMB_COM_WRITE_ANDX:
638: c = "SMB_COM_WRITE_ANDX";
639: break;
640: case SMB_COM_CREATE_DIRECTORY:
641: c = "SMB_COM_CREATE_DIRECTORY";
642: break;
643: default:
644: c = "UNKNOWN";
645: }
646: return new String("command=" + c + ",received=" + received
647: + ",errorCode="
648: + SmbException.getMessageByCode(errorCode)
649: + ",flags=0x" + Gadgets.toHexString(flags & 0xFF, 4)
650: + ",flags2=0x" + Gadgets.toHexString(flags2, 4)
651: + ",signSeq=" + signSeq + ",tid=" + tid + ",pid=" + pid
652: + ",uid=" + uid + ",mid=" + mid + ",wordCount="
653: + wordCount + ",byteCount=" + byteCount);
654: }
655: }
|