KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > knowgate > jcifs > smb > SmbTransport


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

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 JavaDoc;
30 import java.io.OutputStream JavaDoc;
31 import java.io.PushbackInputStream JavaDoc;
32 import java.io.IOException JavaDoc;
33 import java.io.InterruptedIOException JavaDoc;
34 import java.net.InetAddress JavaDoc;
35 import java.net.SocketException JavaDoc;
36 import java.net.UnknownHostException JavaDoc;
37
38 import java.security.MessageDigest JavaDoc;
39
40 import java.util.Arrays JavaDoc;
41 import java.util.LinkedList JavaDoc;
42 import java.util.ListIterator JavaDoc;
43 import java.util.Enumeration JavaDoc;
44 import java.util.HashMap JavaDoc;
45
46
47 class SmbTransport implements Runnable JavaDoc {
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 JavaDoc 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 JavaDoc CONNECTIONS = new LinkedList JavaDoc();
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 JavaDoc responseTable;
98     private InputStream JavaDoc in;
99     private OutputStream JavaDoc out;
100     private int localPort;
101     private InetAddress JavaDoc localAddr;
102     private Thread JavaDoc thread;
103     private Object JavaDoc outLock;
104     private UniAddress address;
105     private int port;
106     private LinkedList JavaDoc sessions;
107     private LinkedList JavaDoc referrals = new LinkedList JavaDoc();
108     private int state;
109     private Mid[] mids = new Mid[MAX_MPX_COUNT];
110     private short mid_next;
111
112     static final String JavaDoc NATIVE_OS =
113             Config.getProperty( "jcifs.smb.client.nativeOs", System.getProperty( "os.name" ));
114     static final String JavaDoc 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 JavaDoc 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         // NT 4 Workstation is 0x43FD
137
int capabilities;
138         String JavaDoc 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 JavaDoc 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 JavaDoc localAddr, int localPort ) {
168         SmbTransport conn;
169
170         synchronized( CONNECTIONS ) {
171             if( SSN_LIMIT != 1 ) {
172                 ListIterator JavaDoc 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 JavaDoc localAddr, int localPort ) {
190         this.address = address;
191         this.port = port;
192         this.localAddr = localAddr;
193         this.localPort = localPort;
194
195         sessions = new LinkedList JavaDoc();
196         responseTable = new HashMap JavaDoc();
197         outLock = new Object JavaDoc();
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 JavaDoc 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 JavaDoc localAddr, int localPort ) {
229         InetAddress JavaDoc defaultLocal = null;
230         try {
231             defaultLocal = InetAddress.getLocalHost();
232         } catch( UnknownHostException JavaDoc 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 JavaDoc la1 = localAddr == null ? defaultLocal : localAddr;
237         InetAddress JavaDoc 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 JavaDoc {
256         if( socket == null ) {
257             Object JavaDoc obj;
258             NbtAddress naddr;
259             String JavaDoc calledName;
260
261             obj = address.getAddress();
262             if( obj instanceof NbtAddress ) {
263                 naddr = (NbtAddress)obj;
264             } else {
265                 try {
266                     naddr = NbtAddress.getByName( ((InetAddress JavaDoc)obj).getHostAddress() );
267                 } catch( UnknownHostException JavaDoc uhe ) {
268                     naddr = null; // never happen
269
}
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 JavaDoc( "Failed to establish session with " + address );
291             }
292
293             /* Save the calledName for using on SMB_COM_TREE_CONNECT
294              */

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 JavaDoc( socket.getInputStream(), PUSHBACK_BUF_SIZE );
305             out = socket.getOutputStream();
306             thread = new Thread JavaDoc( 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 JavaDoc 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 JavaDoc 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                     /* Read on a netbios SocketInputStream does not
376                      * return until len bytes have been read or the stream is
377                      * closed. This must be the latter case.
378                      */

379                     break;
380                 }
381                 ((PushbackInputStream JavaDoc)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 JavaDoc e = (Enumeration JavaDoc)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                     // it's a request(break oplock)
455
}
456 }
457             } catch( InterruptedIOException JavaDoc 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 JavaDoc 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 JavaDoc path ) throws SmbException {
478         String JavaDoc 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                         /* NTLM HTTP Authentication must be re-negotiated
507                          * with challenge from 'server' to access DFS vol. */

508         return dr;
509     }
510     synchronized DfsReferral lookupReferral( String JavaDoc unc ) {
511         DfsReferral dr;
512         ListIterator JavaDoc 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 JavaDoc 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         // now for the normal case where response is not null
568

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                 // default it 1 so that 0 can be used as forever
589
response.wait( response.responseTimeout == 1 ? RESPONSE_TIMEOUT : response.responseTimeout );
590             }
591         } catch( InterruptedException JavaDoc ie ) {
592             tryClose( true );
593         } catch( IOException JavaDoc 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                 // multi-part request
655

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                     // default it 1 so that 0 can be used as forever
727
response.received = false;
728                     response.wait( response.responseTimeout == 1 ? RESPONSE_TIMEOUT : response.responseTimeout );
729                 } while( response.received && response.hasMoreElements() );
730             }
731         } catch( InterruptedException JavaDoc ie ) {
732             tryClose( true );
733         } catch( IOException JavaDoc 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 JavaDoc( "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         /*
791          * Negotiate Protocol Request / Response
792          */

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             // server doesn't want unicode
834
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 JavaDoc toString() {
843         String JavaDoc 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     /* Manage MIDs */
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 JavaDoc 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