+Fri Sep 30 23:28:51 EDT 2005
+jcifs-1.2.5 released / Filter Exceptions, Stressing the Transport Layer,
+ and DFS Deadlock Fixed
+
+This release of the JCIFS client consists of the following changes.
+
+o It was discovered that a flaw in session expiration could cause sessions
+ to expire prematurely. This has been repaired.
+o If the jcifs.netbios.hostname property is set, the client will
+ communicate using only NetBIOS over port 139. This is required for
+ environments that implement a policy restricting users to logging in from
+ certain computers.
+o Under stress the client could incorrectly attempt to use the invalid
+ "NULL" transport. This has been fixed.
+o Filter users could experience exceptions due to using the port 0 rather
+ than the default CIFS port.
+o The client should now handle partial reads and socket exceptions more
+ gracefully.
+o Under stress, the DFS referral query could cause the client to deadlock.
+ This has been fixed.
+
Wed Sep 21 01:53:28 EDT 2005
jcifs-1.2.4 released / Timeout Transport Exception, Bogus Signature Error,
and More
<project name="jcifs" default="usage" basedir=".">
- <property name="version" value="1.2.4"/>
- <property name="reldate" value="Sep 21, 2005"/>
+ <property name="version" value="1.2.5"/>
+ <property name="reldate" value="Oct 1, 2005"/>
<target name="usage">
<echo>
--- /dev/null
+import jcifs.smb.SmbFile;
+import java.util.LinkedList;
+import java.util.ListIterator;
+import java.net.MalformedURLException;
+import java.io.IOException;
+
+public class CrawlTest extends Thread {
+
+ SmbFile f;
+ int maxDepth;
+
+ CrawlTest( SmbFile f, int maxDepth ) {
+ this.f = f;
+ this.maxDepth = maxDepth;
+ }
+
+ void traverse( SmbFile f, int depth ) throws MalformedURLException, IOException {
+
+ if( depth == 0 ) {
+ return;
+ }
+
+ SmbFile[] l = f.listFiles();
+
+ for(int i = 0; l != null && i < l.length; i++ ) {
+ try {
+ for( int j = maxDepth - depth; j > 0; j-- ) {
+ System.out.print( " " );
+ }
+ System.out.println( l[i] + " " + l[i].exists() );
+ if( l[i].isDirectory() ) {
+ traverse( l[i], depth - 1 );
+ }
+ } catch( IOException ioe ) {
+ System.out.println( l[i] + ":" );
+ ioe.printStackTrace( System.out );
+ }
+ }
+ }
+
+ public void run() {
+ try {
+ traverse( f, maxDepth );
+ } catch( Exception ex ) {
+ ex.printStackTrace();
+ }
+ }
+
+ public static void main(String[] argv) throws Exception {
+ if (argv.length < 3) {
+ System.err.println( "CrawlTest <url> <numthreads> <maxdepth>" );
+ return;
+ }
+
+ SmbFile f = new SmbFile( argv[0] );
+ int numThreads = Integer.parseInt( argv[1] );
+ int maxDepth = Integer.parseInt( argv[2] );
+
+ while (numThreads-- > 0 && System.in.read() == '\n') {
+ CrawlTest sc = new CrawlTest( f, maxDepth );
+ sc.start();
+ }
+ }
+}
+++ /dev/null
-import jcifs.netbios.NbtAddress;
-import jcifs.*;
-import jcifs.smb.*;
-
-public class CheckAllDC {
-
- public static void main( String argv[] ) throws Exception {
-
- NbtAddress[] addrs = NbtAddress.getAllByName( argv[0], 0x1C, null, null );
-
- for( int i = 0; i < addrs.length; i++ ) {
- System.out.println( addrs[i] );
- UniAddress dc = new UniAddress( addrs[i] );
- NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication( argv[1] );
- SmbSession.logon( dc, auth );
- }
- }
-}
static final boolean USE_NTSMBS = Config.getBoolean( "jcifs.smb.client.useNTSmbs", true );
static final boolean USE_EXTSEC = Config.getBoolean( "jcifs.smb.client.useExtendedSecurity", false );
+ static final String NETBIOS_HOSTNAME = Config.getProperty( "jcifs.netbios.hostname", null );
+
static final int FLAGS_NONE = 0x00;
static final int FLAGS_LOCK_AND_READ_WRITE_AND_UNLOCK = 0x01;
static final int FLAGS_RECEIVE_BUFFER_POSTED = 0x02;
private int port, localPort;
private InetAddress localAddr;
- SmbTransport transport = SmbTransport.NULL_TRANSPORT;
+ SmbTransport transport = null;
NtlmPasswordAuthentication auth;
long expiration;
boolean matches( NtlmPasswordAuthentication auth ) {
return this.auth == auth || this.auth.equals( auth );
}
- synchronized SmbTransport transport() throws SmbException {
- if( transport == SmbTransport.NULL_TRANSPORT ) {
+ synchronized SmbTransport transport() {
+ if( transport == null ) {
transport = SmbTransport.getSmbTransport( address, port, localAddr, localPort );
}
return transport;
if( response != null ) {
response.received = false;
}
+ expiration = System.currentTimeMillis() + SmbTransport.SO_TIMEOUT;
sessionSetup( request, response );
if( response != null && response.received ) {
return;
}
request.uid = uid;
request.auth = auth;
- transport().send( request, response );
+ transport.send( request, response );
}
void sessionSetup( ServerMessageBlock andx,
ServerMessageBlock andxResponse ) throws SmbException {
return;
}
- expiration = System.currentTimeMillis() + SmbTransport.SO_TIMEOUT;
-
transport.connect();
/*
}
}
void logoff( boolean inError ) {
-synchronized( transport ) {
- try {
- if( sessionSetup == false ) {
- return;
- }
+synchronized( transport() ) {
+ if( sessionSetup == false ) {
+ return;
+ }
- for( Enumeration e = trees.elements(); e.hasMoreElements(); ) {
- SmbTree t = (SmbTree)e.nextElement();
- t.treeDisconnect( inError );
- }
+ for( Enumeration e = trees.elements(); e.hasMoreElements(); ) {
+ SmbTree t = (SmbTree)e.nextElement();
+ t.treeDisconnect( inError );
+ }
- if( !inError && transport.server.security != ServerMessageBlock.SECURITY_SHARE ) {
+ if( !inError && transport.server.security != ServerMessageBlock.SECURITY_SHARE ) {
- /*
- * Logoff And X Request / Response
- */
+ /*
+ * Logoff And X Request / Response
+ */
- SmbComLogoffAndX request = new SmbComLogoffAndX( null );
- request.uid = uid;
- try {
- transport.send( request, null );
- } catch( SmbException se ) {
- }
+ SmbComLogoffAndX request = new SmbComLogoffAndX( null );
+ request.uid = uid;
+ try {
+ transport.send( request, null );
+ } catch( SmbException se ) {
}
-
- sessionSetup = false;
- } finally {
- transport = SmbTransport.NULL_TRANSPORT;
}
+
+ sessionSetup = false;
}
}
public String toString() {
return ssn;
}
boolean matches( UniAddress address, int port, InetAddress localAddr, int localPort ) {
- int p1 = ( port == 0 || port == DEFAULT_PORT ) ? 0 : port;
- int p2 = ( this.port == 0 || this.port == DEFAULT_PORT ) ? 0 : this.port;
return address.equals( this.address ) &&
- p1 == p2 &&
+ (port == 0 || port == this.port) &&
(localAddr == this.localAddr ||
(localAddr != null &&
localAddr.equals( this.localAddr ))) &&
* until we have properly negotiated.
*/
synchronized (sbuf) {
+ /* If jcifs.netbios.hostname is set this *probably* means there
+ * is a policy regarding which hosts a user can connect from. This
+ * requires communicating over port 139 rather than 445.
+ */
+ if (NETBIOS_HOSTNAME != null && NETBIOS_HOSTNAME.equals( "" ) == false) {
+ port = 139;
+ }
if (port == 139) {
ssn139();
} else {
+ if (port == 0)
+ port = DEFAULT_PORT; // 445
if (localAddr == null) {
socket = new Socket( address.getHostAddress(), port );
} else {
/* Note the Transport thread isn't running yet so we can
* read from the socket here.
*/
- peekKey(); /* try to read header */
+ if (peekKey() == null) /* try to read header */
+ throw new IOException( "transport closed in negotiate" );
int size = Encdec.dec_uint16be( sbuf, 2 );
if (size < 33 || (4 + size) > sbuf.length ) {
throw new IOException( "Invalid payload size: " + size );
try {
negotiate( port, resp );
} catch( ConnectException ce ) {
- port = port == 445 ? 139 : 445;
+ port = (port == 0 || port == DEFAULT_PORT) ? 139 : DEFAULT_PORT;
negotiate( port, resp );
}
protected Request peekKey() throws IOException {
int n;
do {
- n = readn( in, sbuf, 0, 4 );
+ if ((n = readn( in, sbuf, 0, 4 )) < 4)
+ return null;
} while (sbuf[0] == (byte)0x85); /* Dodge NetBIOS keep-alive */
/* read smb header */
- if ((n = readn( in, sbuf, 4, 32 )) < 32) {
- return null; /* stream closed */
- }
+ if ((n = readn( in, sbuf, 4, 32 )) < 32)
+ return null;
if (log.level > 2) {
log.println( "New data read: " + this );
jcifs.util.Hexdump.hexdump( log, sbuf, 4, 32 );
/* DFS */
- synchronized DfsReferral getDfsReferral( NtlmPasswordAuthentication auth,
+ DfsReferral getDfsReferral( NtlmPasswordAuthentication auth,
String path ) throws SmbException {
String subpath, node, host;
DfsReferral dr = new DfsReferral();
* with challenge from 'server' to access DFS vol. */
return dr;
}
- synchronized DfsReferral lookupReferral( String unc ) {
- DfsReferral dr;
- ListIterator iter = referrals.listIterator();
- int i, len;
+ DfsReferral lookupReferral( String unc ) {
+ synchronized( referrals ) {
+ DfsReferral dr;
+ ListIterator iter = referrals.listIterator();
+ int i, len;
- while( iter.hasNext() ) {
- dr = (DfsReferral)iter.next();
- len = dr.path.length();
- for( i = 0; i < len && i < unc.length(); i++ ) {
- if( dr.path.charAt( i ) != unc.charAt( i )) {
- break;
+ while( iter.hasNext() ) {
+ dr = (DfsReferral)iter.next();
+ len = dr.path.length();
+ for( i = 0; i < len && i < unc.length(); i++ ) {
+ if( dr.path.charAt( i ) != unc.charAt( i )) {
+ break;
+ }
+ }
+ if( i == len && (len == unc.length() || unc.charAt( len ) == '\\')) {
+ return dr;
}
- }
- if( i == len && (len == unc.length() || unc.charAt( len ) == '\\')) {
- return dr;
}
}
while( thread == Thread.currentThread() ) {
try {
Request key = peekKey();
- if (key == null) return;
+ if (key == null)
+ throw new IOException( "end of stream" );
synchronized (response_map) {
Response response = (Response)response_map.get( key );
if (response == null) {