KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jcifs > smb > ServerMessageBlock


1 /* jcifs smb client library in Java
2  * Copyright (C) 2000 "Michael B. Allen" <jcifs at samba dot org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */

18
19 package jcifs.smb;
20
21 import jcifs.Config;
22 import java.io.InputStream JavaDoc;
23 import java.io.PushbackInputStream JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.UnsupportedEncodingException JavaDoc;
26 import java.util.Calendar JavaDoc;
27 import java.util.Date JavaDoc;
28 import jcifs.util.Hexdump;
29 import jcifs.util.LogStream;
30 import jcifs.util.transport.*;
31
32 abstract class ServerMessageBlock extends Response implements Request, SmbConstants {
33
34     static LogStream log = LogStream.getInstance();
35
36     static final byte[] header = {
37         (byte)0xFF, (byte)'S', (byte)'M', (byte)'B',
38         (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
39         (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
40         (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
41         (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
42         (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00
43     };
44
45     static void writeInt2( long val, byte[] dst, int dstIndex ) {
46         dst[dstIndex] = (byte)(val);
47         dst[++dstIndex] = (byte)(val >> 8);
48     }
49     static void writeInt4( long val, byte[] dst, int dstIndex ) {
50         dst[dstIndex] = (byte)(val);
51         dst[++dstIndex] = (byte)(val >>= 8);
52         dst[++dstIndex] = (byte)(val >>= 8);
53         dst[++dstIndex] = (byte)(val >> 8);
54     }
55     static int readInt2( byte[] src, int srcIndex ) {
56         return ( src[srcIndex] & 0xFF ) +
57                 (( src[srcIndex + 1] & 0xFF ) << 8 );
58     }
59     static int readInt4( byte[] src, int srcIndex ) {
60         return ( src[srcIndex] & 0xFF ) +
61                 (( src[srcIndex + 1] & 0xFF ) << 8 ) +
62                 (( src[srcIndex + 2] & 0xFF ) << 16 ) +
63                 (( src[srcIndex + 3] & 0xFF ) << 24 );
64     }
65     static long readInt8( byte[] src, int srcIndex ) {
66         return (readInt4( src, srcIndex ) & 0xFFFFFFFFL) +
67             ((long)(readInt4( src, srcIndex + 4 )) << 32);
68     }
69     static void writeInt8( long val, byte[] dst, int dstIndex ) {
70         dst[dstIndex] = (byte)(val);
71         dst[++dstIndex] = (byte)(val >>= 8);
72         dst[++dstIndex] = (byte)(val >>= 8);
73         dst[++dstIndex] = (byte)(val >>= 8);
74         dst[++dstIndex] = (byte)(val >>= 8);
75         dst[++dstIndex] = (byte)(val >>= 8);
76         dst[++dstIndex] = (byte)(val >>= 8);
77         dst[++dstIndex] = (byte)(val >> 8);
78     }
79     static long readTime( byte[] src, int srcIndex ) {
80         int low = readInt4( src, srcIndex );
81         int hi = readInt4( src, srcIndex + 4 );
82         long t = ((long)hi << 32L ) | (low & 0xFFFFFFFFL);
83         t = ( t / 10000L - MILLISECONDS_BETWEEN_1970_AND_1601 );
84         return t;
85     }
86     static void writeTime( long t, byte[] dst, int dstIndex ) {
87         if( t != 0L ) {
88             t = (t + MILLISECONDS_BETWEEN_1970_AND_1601) * 10000L;
89         }
90         writeInt8( t, dst, dstIndex );
91     }
92     static long readUTime( byte[] buffer, int bufferIndex ) {
93         return readInt4( buffer, bufferIndex ) * 1000L;
94     }
95     static void writeUTime( long t, byte[] dst, int dstIndex ) {
96         if( t == 0L || t == 0xFFFFFFFFFFFFFFFFL ) {
97             writeInt4( 0xFFFFFFFF, dst, dstIndex );
98             return;
99         }
100         synchronized( TZ ) {
101             if( TZ.inDaylightTime( new Date JavaDoc() )) {
102                 // in DST
103
if( TZ.inDaylightTime( new Date JavaDoc( t ))) {
104                     // t also in DST so no correction
105
} else {
106                     // t not in DST so subtract 1 hour
107
t -= 3600000;
108                 }
109             } else {
110                 // not in DST
111
if( TZ.inDaylightTime( new Date JavaDoc( t ))) {
112                     // t is in DST so add 1 hour
113
t += 3600000;
114                 } else {
115                     // t isn't in DST either
116
}
117             }
118         }
119         writeInt4( (int)(t / 1000L), dst, dstIndex );
120     }
121
122     /*
123      * These are all the smbs supported by this library. This includes requests
124      * and well as their responses for each type however the actuall implementations
125      * of the readXxxWireFormat and writeXxxWireFormat methods may not be in
126      * place. For example at the time of this writing the readXxxWireFormat
127      * for requests and the writeXxxWireFormat for responses are not implemented
128      * and simply return 0. These would need to be completed for a server
129      * implementation.
130      */

131
132     static final byte SMB_COM_CREATE_DIRECTORY = (byte)0x00;
133     static final byte SMB_COM_DELETE_DIRECTORY = (byte)0x01;
134     static final byte SMB_COM_CLOSE = (byte)0x04;
135     static final byte SMB_COM_DELETE = (byte)0x06;
136     static final byte SMB_COM_RENAME = (byte)0x07;
137     static final byte SMB_COM_QUERY_INFORMATION = (byte)0x08;
138     static final byte SMB_COM_WRITE = (byte)0x0B;
139     static final byte SMB_COM_CHECK_DIRECTORY = (byte)0x10;
140     static final byte SMB_COM_TRANSACTION = (byte)0x25;
141     static final byte SMB_COM_TRANSACTION_SECONDARY = (byte)0x26;
142     static final byte SMB_COM_MOVE = (byte)0x2A;
143     static final byte SMB_COM_ECHO = (byte)0x2B;
144     static final byte SMB_COM_OPEN_ANDX = (byte)0x2D;
145     static final byte SMB_COM_READ_ANDX = (byte)0x2E;
146     static final byte SMB_COM_WRITE_ANDX = (byte)0x2F;
147     static final byte SMB_COM_TRANSACTION2 = (byte)0x32;
148     static final byte SMB_COM_FIND_CLOSE2 = (byte)0x34;
149     static final byte SMB_COM_TREE_DISCONNECT = (byte)0x71;
150     static final byte SMB_COM_NEGOTIATE = (byte)0x72;
151     static final byte SMB_COM_SESSION_SETUP_ANDX = (byte)0x73;
152     static final byte SMB_COM_LOGOFF_ANDX = (byte)0x74;
153     static final byte SMB_COM_TREE_CONNECT_ANDX = (byte)0x75;
154     static final byte SMB_COM_NT_TRANSACT = (byte)0xA0;
155     static final byte SMB_COM_NT_TRANSACT_SECONDARY = (byte)0xA1;
156     static final byte SMB_COM_NT_CREATE_ANDX = (byte)0xA2;
157
158     /*
159      * Some fields specify the offset from the beginning of the header. This
160      * field should be used for calculating that. This would likely be zero
161      * but an implemantation that encorporates the transport header(for
162      * efficiency) might use a different initial bufferIndex. For example,
163      * to eliminate copying data when writing NbtSession data one might
164      * manage that 4 byte header specifically and therefore the initial
165      * bufferIndex, and thus headerStart, would be 4).(NOTE: If one where
166      * looking for a way to improve perfomance this is precisly what you
167      * would want to do as the jcifs.netbios.SocketXxxputStream classes
168      * arraycopy all data read or written into a new buffer shifted over 4!)
169      */

170
171     byte command, flags;
172     int headerStart,
173         length,
174         batchLevel,
175         errorCode,
176         flags2,
177         tid, pid, uid, mid,
178         wordCount, byteCount;
179     boolean useUnicode, received;
180     long responseTimeout = 1;
181     int signSeq;
182     boolean verifyFailed;
183     NtlmPasswordAuthentication auth = null;
184     String JavaDoc path;
185     SigningDigest digest = null;
186     ServerMessageBlock response;
187
188     ServerMessageBlock() {
189         flags = (byte)( FLAGS_PATH_NAMES_CASELESS | FLAGS_PATH_NAMES_CANONICALIZED );
190         pid = PID;
191         batchLevel = 0;
192     }
193
194     void reset() {
195         flags = (byte)( FLAGS_PATH_NAMES_CASELESS | FLAGS_PATH_NAMES_CANONICALIZED );
196         flags2 = 0;
197         errorCode = 0;
198         received = false;
199         digest = null;
200     }
201     int writeString( String JavaDoc str, byte[] dst, int dstIndex ) {
202         return writeString( str, dst, dstIndex, useUnicode );
203     }
204     int writeString( String JavaDoc str, byte[] dst, int dstIndex, boolean useUnicode ) {
205         int start = dstIndex;
206
207         try {
208             if( useUnicode ) {
209                 // Unicode requires word alignment
210
if((( dstIndex - headerStart ) % 2 ) != 0 ) {
211                     dst[dstIndex++] = (byte)'\0';
212                 }
213                 System.arraycopy( str.getBytes( "UnicodeLittleUnmarked" ), 0,
214                                     dst, dstIndex, str.length() * 2 );
215                 dstIndex += str.length() * 2;
216                 dst[dstIndex++] = (byte)'\0';
217                 dst[dstIndex++] = (byte)'\0';
218             } else {
219                 byte[] b = str.getBytes( OEM_ENCODING );
220                 System.arraycopy( b, 0, dst, dstIndex, b.length );
221                 dstIndex += b.length;
222                 dst[dstIndex++] = (byte)'\0';
223             }
224         } catch( UnsupportedEncodingException JavaDoc uee ) {
225             if( log.level > 1 )
226                 uee.printStackTrace( log );
227         }
228
229         return dstIndex - start;
230     }
231     String JavaDoc readString( byte[] src, int srcIndex ) {
232         return readString( src, srcIndex, 256, useUnicode );
233     }
234     String JavaDoc readString( byte[] src, int srcIndex, int maxLen, boolean useUnicode ) {
235         int len = 0;
236         String JavaDoc str = null;
237         try {
238             if( useUnicode ) {
239                 // Unicode requires word alignment
240
if((( srcIndex - headerStart ) % 2 ) != 0 ) {
241                     srcIndex++;
242                 }
243                 while( src[srcIndex + len] != (byte)0x00 ||
244                                             src[srcIndex + len + 1] != (byte)0x00 ) {
245                     len += 2;
246                     if( len > maxLen ) {
247 if( log.level > 0 )
248 Hexdump.hexdump( System.err, src, srcIndex, maxLen < 128 ? maxLen + 8 : 128 );
249                         throw new RuntimeException JavaDoc( "zero termination not found" );
250                     }
251                 }
252                 str = new String JavaDoc( src, srcIndex, len, "UnicodeLittleUnmarked" );
253             } else {
254                 while( src[srcIndex + len] != (byte)0x00 ) {
255                     len++;
256                     if( len > maxLen ) {
257 if( log.level > 0 )
258 Hexdump.hexdump( System.err, src, srcIndex, maxLen < 128 ? maxLen + 8 : 128 );
259                         throw new RuntimeException JavaDoc( "zero termination not found" );
260                     }
261                 }
262                 str = new String JavaDoc( src, srcIndex, len, OEM_ENCODING );
263             }
264         } catch( UnsupportedEncodingException JavaDoc uee ) {
265             if( log.level > 1 )
266                 uee.printStackTrace( log );
267         }
268         return str;
269     }
270     int stringWireLength( String JavaDoc str, int offset ) {
271         int len = str.length() + 1;
272         if( useUnicode ) {
273             len = str.length() * 2 + 2;
274             len = ( offset % 2 ) != 0 ? len + 1 : len;
275         }
276         return len;
277     }
278     int readStringLength( byte[] src, int srcIndex, int max ) {
279         int len = 0;
280         while( src[srcIndex + len] != (byte)0x00 ) {
281             if( len++ > max ) {
282                 throw new RuntimeException JavaDoc( "zero termination not found: " + this );
283             }
284         }
285         return len;
286     }
287     int encode( byte[] dst, int dstIndex ) {
288         int start = headerStart = dstIndex;
289
290         dstIndex += writeHeaderWireFormat( dst, dstIndex );
291         wordCount = writeParameterWordsWireFormat( dst, dstIndex + 1 );
292         dst[dstIndex++] = (byte)(( wordCount / 2 ) & 0xFF );
293         dstIndex += wordCount;
294         wordCount /= 2;
295         byteCount = writeBytesWireFormat( dst, dstIndex + 2 );
296         dst[dstIndex++] = (byte)( byteCount & 0xFF );
297         dst[dstIndex++] = (byte)(( byteCount >> 8 ) & 0xFF );
298         dstIndex += byteCount;
299
300         length = dstIndex - start;
301
302         if( digest != null ) {
303             digest.sign( dst, headerStart, length, this, response );
304         }
305
306         return length;
307     }
308     int decode( byte[] buffer, int bufferIndex ) {
309         int start = headerStart = bufferIndex;
310
311         bufferIndex += readHeaderWireFormat( buffer, bufferIndex );
312
313         wordCount = buffer[bufferIndex++];
314         if( wordCount != 0 ) {
315             int n;
316             if(( n = readParameterWordsWireFormat( buffer, bufferIndex )) != wordCount * 2 ) {
317                 if( log.level >= 5 ) {
318                     log.println( "wordCount * 2=" + ( wordCount * 2 ) +
319                             " but readParameterWordsWireFormat returned " + n );
320                 }
321             }
322             bufferIndex += wordCount * 2;
323         }
324
325         byteCount = readInt2( buffer, bufferIndex );
326         bufferIndex += 2;
327
328         if( byteCount != 0 ) {
329             int n;
330             if(( n = readBytesWireFormat( buffer, bufferIndex )) != byteCount ) {
331                 if( log.level >= 5 ) {
332                     log.println( "byteCount=" + byteCount +
333                             " but readBytesWireFormat returned " + n );
334                 }
335             }
336             // Don't think we can rely on n being correct here. Must use byteCount.
337
// Last paragraph of section 3.13.3 eludes to this.
338

339             bufferIndex += byteCount;
340         }
341
342         length = bufferIndex - start;
343         return length;
344     }
345     int writeHeaderWireFormat( byte[] dst, int dstIndex ) {
346         System.arraycopy( header, 0, dst, dstIndex, header.length );
347         dst[dstIndex + CMD_OFFSET] = command;
348         dst[dstIndex + FLAGS_OFFSET] = flags;
349         writeInt2( flags2, dst, dstIndex + FLAGS_OFFSET + 1 );
350         dstIndex += TID_OFFSET;
351         writeInt2( tid, dst, dstIndex );
352         writeInt2( pid, dst, dstIndex + 2 );
353         writeInt2( uid, dst, dstIndex + 4 );
354         writeInt2( mid, dst, dstIndex + 6 );
355         return HEADER_LENGTH;
356     }
357     int readHeaderWireFormat( byte[] buffer, int bufferIndex ) {
358         command = buffer[bufferIndex + CMD_OFFSET];
359         errorCode = readInt4( buffer, bufferIndex + ERROR_CODE_OFFSET );
360         flags = buffer[bufferIndex + FLAGS_OFFSET];
361         flags2 = readInt2( buffer, bufferIndex + FLAGS_OFFSET + 1 );
362         tid = readInt2( buffer, bufferIndex + TID_OFFSET );
363         pid = readInt2( buffer, bufferIndex + TID_OFFSET + 2 );
364         uid = readInt2( buffer, bufferIndex + TID_OFFSET + 4 );
365         mid = readInt2( buffer, bufferIndex + TID_OFFSET + 6 );
366         return HEADER_LENGTH;
367     }
368     boolean isResponse() {
369         return ( flags & FLAGS_RESPONSE ) == FLAGS_RESPONSE;
370     }
371
372     /*
373      * For this packet deconstruction technique to work for
374      * other networking protocols the InputStream may need
375      * to be passed to the readXxxWireFormat methods. This is
376      * actually purer. However, in the case of smb we know the
377      * wordCount and byteCount. And since every subclass of
378      * ServerMessageBlock would have to perform the same read
379      * operation on the input stream, we might as will pull that
380      * common functionality into the superclass and read wordCount
381      * and byteCount worth of data.
382      *
383      * We will still use the readXxxWireFormat return values to
384      * indicate how many bytes(note: readParameterWordsWireFormat
385      * returns bytes read and not the number of words(but the
386      * wordCount member DOES store the number of words)) we
387      * actually read. Incedentally this is important to the
388      * AndXServerMessageBlock class that needs to potentially
389      * read in another smb's parameter words and bytes based on
390      * information in it's andxCommand, andxOffset, ...etc.
391      */

392
393     abstract int writeParameterWordsWireFormat( byte[] dst, int dstIndex );
394     abstract int writeBytesWireFormat( byte[] dst, int dstIndex );
395     abstract int readParameterWordsWireFormat( byte[] buffer, int bufferIndex );
396     abstract int readBytesWireFormat( byte[] buffer, int bufferIndex );
397
398     public int hashCode() {
399         return mid;
400     }
401     public boolean equals( Object JavaDoc obj ) {
402         return obj instanceof ServerMessageBlock && ((ServerMessageBlock)obj).mid == mid;
403     }
404     public String JavaDoc toString() {
405         String JavaDoc c;
406         switch( command ) {
407             case SMB_COM_NEGOTIATE:
408                 c = "SMB_COM_NEGOTIATE";
409                 break;
410             case SMB_COM_SESSION_SETUP_ANDX:
411                 c = "SMB_COM_SESSION_SETUP_ANDX";
412                 break;
413             case SMB_COM_TREE_CONNECT_ANDX:
414                 c = "SMB_COM_TREE_CONNECT_ANDX";
415                 break;
416             case SMB_COM_QUERY_INFORMATION:
417                 c = "SMB_COM_QUERY_INFORMATION";
418                 break;
419             case SMB_COM_CHECK_DIRECTORY:
420                 c = "SMB_COM_CHECK_DIRECTORY";
421                 break;
422             case SMB_COM_TRANSACTION:
423                 c = "SMB_COM_TRANSACTION";
424                 break;
425             case SMB_COM_TRANSACTION2:
426                 c = "SMB_COM_TRANSACTION2";
427                 break;
428             case SMB_COM_TRANSACTION_SECONDARY:
429                 c = "SMB_COM_TRANSACTION_SECONDARY";
430                 break;
431             case SMB_COM_FIND_CLOSE2:
432                 c = "SMB_COM_FIND_CLOSE2";
433                 break;
434             case SMB_COM_TREE_DISCONNECT:
435                 c = "SMB_COM_TREE_DISCONNECT";
436                 break;
437             case SMB_COM_LOGOFF_ANDX:
438                 c = "SMB_COM_LOGOFF_ANDX";
439                 break;
440             case SMB_COM_ECHO:
441                 c = "SMB_COM_ECHO";
442                 break;
443             case SMB_COM_MOVE:
444                 c = "SMB_COM_MOVE";
445                 break;
446             case SMB_COM_RENAME:
447                 c = "SMB_COM_RENAME";
448                 break;
449             case SMB_COM_DELETE:
450                 c = "SMB_COM_DELETE";
451                 break;
452             case SMB_COM_DELETE_DIRECTORY:
453                 c = "SMB_COM_DELETE_DIRECTORY";
454                 break;
455             case SMB_COM_NT_CREATE_ANDX:
456                 c = "SMB_COM_NT_CREATE_ANDX";
457                 break;
458             case SMB_COM_OPEN_ANDX:
459                 c = "SMB_COM_OPEN_ANDX";
460                 break;
461             case SMB_COM_READ_ANDX:
462                 c = "SMB_COM_READ_ANDX";
463                 break;
464             case SMB_COM_CLOSE:
465                 c = "SMB_COM_CLOSE";
466                 break;
467             case SMB_COM_WRITE_ANDX:
468                 c = "SMB_COM_WRITE_ANDX";
469                 break;
470             case SMB_COM_CREATE_DIRECTORY:
471                 c = "SMB_COM_CREATE_DIRECTORY";
472                 break;
473             case SMB_COM_NT_TRANSACT:
474                 c = "SMB_COM_NT_TRANSACT";
475                 break;
476             case SMB_COM_NT_TRANSACT_SECONDARY:
477                 c = "SMB_COM_NT_TRANSACT_SECONDARY";
478                 break;
479             default:
480                 c = "UNKNOWN";
481         }
482         String JavaDoc str = errorCode == 0 ? "0" : SmbException.getMessageByCode( errorCode );
483         return new String JavaDoc(
484             "command=" + c +
485             ",received=" + received +
486             ",errorCode=" + str +
487             ",flags=0x" + Hexdump.toHexString( flags & 0xFF, 4 ) +
488             ",flags2=0x" + Hexdump.toHexString( flags2, 4 ) +
489             ",signSeq=" + signSeq +
490             ",tid=" + tid +
491             ",pid=" + pid +
492             ",uid=" + uid +
493             ",mid=" + mid +
494             ",wordCount=" + wordCount +
495             ",byteCount=" + byteCount );
496     }
497 }
498
Popular Tags