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