From: Felix Schumacher Date: Wed, 6 Aug 2008 14:47:28 +0000 (+0200) Subject: jcifs-1.2.22 from tgz X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=195d57b57a3dbc231ecb2432195bedc1b5bab628;p=jcifs_without_docs.git jcifs-1.2.22 from tgz Wed Jun 25 20:26:33 EDT 2008 jcifs-1.2.22 The SmbFileInputStream methods will now throw InterruptedIOExceptions where apppropriate whereas previously they would throw SmbExceptions with a root cause of TransportException with a root cause of InterruptedException. If SmbSession.send() throw an exception it could leave the session in a bad state which could cause "Invalid parameter" exceptions on subsequent requests. An InterruptedException in jcifs.netbios.NameServiceClient was being caught and ignored. It will now be re-thrown as an IOException so that all threads used with/by JCIFS can be interrupted and caused to exit. Several other similar (albeit less important) InterruptedExceptions were also adjusted. A jcifs.smb.client.dfs.disabled property has been added to disable domain based DFS so that the client does not try and fail to resolve paths as domain paths in non-domain environments (e.g. on the local machine). The getSecurity and getShareSecurity methods will now return null if no DACL is present on a file whereas previously it would retrun an empty array. This allows the caller to distinguish between an empty DACL and one that is simply empty. --- diff --git a/README.txt b/README.txt index e939aae..c2b2b27 100644 --- a/README.txt +++ b/README.txt @@ -1,4 +1,32 @@ +Wed Jun 25 20:26:33 EDT 2008 +jcifs-1.2.22 + +The SmbFileInputStream methods will now throw InterruptedIOExceptions +where apppropriate whereas previously they would throw SmbExceptions +with a root cause of TransportException with a root cause of +InterruptedException. + +If SmbSession.send() throw an exception it could leave the session in a +bad state which could cause "Invalid parameter" exceptions on subsequent +requests. + +An InterruptedException in jcifs.netbios.NameServiceClient was being +caught and ignored. It will now be re-thrown as an IOException so that all +threads used with/by JCIFS can be interrupted and caused to exit. Several +other similar (albeit less important) InterruptedExceptions were also +adjusted. + +A jcifs.smb.client.dfs.disabled property has been added to disable domain +based DFS so that the client does not try and fail to resolve paths as +domain paths in non-domain environments (e.g. on the local machine). + +The getSecurity and getShareSecurity methods will now return null if no +DACL is present on a file whereas previously it would retrun an empty +array. This allows the caller to distinguish between an empty DACL and +one that is simply empty. + Wed May 28 22:46:56 EDT 2008 +jcifs-1.2.21 An NPE in jcifs.Config was accidentally introduced in 1.2.20. This has been fixed. diff --git a/build.xml b/build.xml index 8a20066..5943d4d 100644 --- a/build.xml +++ b/build.xml @@ -1,7 +1,7 @@ - - + + diff --git a/examples/InterruptTest.java b/examples/InterruptTest.java index 63cffab..0ba5c37 100644 --- a/examples/InterruptTest.java +++ b/examples/InterruptTest.java @@ -1,3 +1,4 @@ +import java.io.InterruptedIOException; import jcifs.util.transport.TransportException; import jcifs.smb.*; @@ -9,7 +10,7 @@ public class InterruptTest extends Thread { this.url = url; } public void run() { - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 100; i++) { try { SmbFileInputStream in = new SmbFileInputStream(url); @@ -19,13 +20,16 @@ public class InterruptTest extends Thread { } in.close(); + } catch(InterruptedIOException iioe) { + System.out.println("InterruptedIOException"); + continue; } catch(SmbException se) { Throwable t = se.getRootCause(); if (t instanceof TransportException) { TransportException te = (TransportException)t; t = te.getRootCause(); if (t instanceof InterruptedException) { - System.out.println("interrupted ok"); + System.out.println("InterruptedException in constructor"); continue; } } @@ -41,8 +45,7 @@ public class InterruptTest extends Thread { public static void main( String argv[] ) throws Exception { InterruptTest it = new InterruptTest(argv[0]); it.start(); - Thread.sleep(300); - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 20; i++) { Thread.sleep(200); it.interrupt(); } diff --git a/examples/runtests.sh b/examples/runtests.sh index 670504c..fd592b3 100644 --- a/examples/runtests.sh +++ b/examples/runtests.sh @@ -6,7 +6,7 @@ PROPERTIES=../../user1.prp RUN="${JAVA_HOME}/bin/java -cp ${CLASSPATH} -Djcifs.properties=${PROPERTIES}" SERVER=dc1.w.net -SHARE=target1 +SHARE=tmp WRITE_DIR=test/ SRC_DIR=test/Junk FILE1=test/Junk/10883563.doc @@ -27,7 +27,7 @@ $RUN GetSecurity ${URL_SHARE} $RUN GetShareSecurity ${URL_WRITE_DIR} $RUN SidCrawler ${URL_WRITE_DIR} 5 $RUN GetGroupMemberSidsFromURL ${URL_WRITE_DIR} -$RUN InterruptTest ${URL_WRITE_DIR}Append.txt +$RUN InterruptTest ${URL_WRITE_DIR}${FILE1} $RUN AllocInfo ${URL_SHARE} $RUN Append ${URL_WRITE_DIR}Append.txt $RUN AuthListFiles smb://bogus\@${SERVER}/${SHARE}/ diff --git a/src/jcifs/dcerpc/DcerpcHandle.java b/src/jcifs/dcerpc/DcerpcHandle.java index 193fd30..7786a82 100644 --- a/src/jcifs/dcerpc/DcerpcHandle.java +++ b/src/jcifs/dcerpc/DcerpcHandle.java @@ -131,7 +131,11 @@ public abstract class DcerpcHandle implements DcerpcConstants { isDirect = msg instanceof DcerpcBind; - stub = jcifs.smb.BufferCache.getBuffer(); + try { + stub = jcifs.smb.BufferCache.getBuffer(); + } catch (InterruptedException ie) { + throw new IOException(ie.getMessage()); + } try { int off, tot, n; diff --git a/src/jcifs/dcerpc/msrpc/MsrpcShareGetInfo.java b/src/jcifs/dcerpc/msrpc/MsrpcShareGetInfo.java index a795a12..d7c1081 100644 --- a/src/jcifs/dcerpc/msrpc/MsrpcShareGetInfo.java +++ b/src/jcifs/dcerpc/msrpc/MsrpcShareGetInfo.java @@ -19,6 +19,8 @@ package jcifs.dcerpc.msrpc; +import java.io.IOException; + import jcifs.smb.*; import jcifs.util.Hexdump; @@ -30,13 +32,13 @@ public class MsrpcShareGetInfo extends srvsvc.ShareGetInfo { flags = DCERPC_FIRST_FRAG | DCERPC_LAST_FRAG; } - public ACE[] getSecurity() { + public ACE[] getSecurity() throws IOException { srvsvc.ShareInfo502 info502 = (srvsvc.ShareInfo502)info; if (info502.security_descriptor != null) { SecurityDescriptor sd; sd = new SecurityDescriptor(info502.security_descriptor, 0, info502.sd_size); return sd.aces; } - return new ACE[0]; + return null; } } diff --git a/src/jcifs/netbios/NameServiceClient.java b/src/jcifs/netbios/NameServiceClient.java index bc3bdf2..c250986 100644 --- a/src/jcifs/netbios/NameServiceClient.java +++ b/src/jcifs/netbios/NameServiceClient.java @@ -20,7 +20,6 @@ package jcifs.netbios; import java.net.*; import java.io.IOException; -import java.io.InterruptedIOException; import java.util.HashMap; import java.util.StringTokenizer; import jcifs.Config; @@ -145,8 +144,6 @@ class NameServiceClient implements Runnable { // be ignored; see tryClose comment. if( socket == null ) { socket = new DatagramSocket( lport, laddr ); -jcifs.Config.socketCount++; -log.println(jcifs.Config.socketCount + ": new Socket: " + socket); thread = new Thread( this, "JCIFS-NameServiceClient" ); thread.setDaemon( true ); thread.start(); @@ -164,10 +161,7 @@ log.println(jcifs.Config.socketCount + ": new Socket: " + socket); */ if( socket != null ) { -String s = socket.toString(); socket.close(); -jcifs.Config.socketCount--; -log.println(jcifs.Config.socketCount + ": socket closed: " + s); socket = null; } thread = null; @@ -259,6 +253,7 @@ log.println(jcifs.Config.socketCount + ": socket closed: " + s); } } catch( InterruptedException ie ) { + throw new IOException(ie.getMessage()); } finally { responseTable.remove( nid ); } diff --git a/src/jcifs/smb/BufferCache.java b/src/jcifs/smb/BufferCache.java index 17f97bf..14fa4fa 100644 --- a/src/jcifs/smb/BufferCache.java +++ b/src/jcifs/smb/BufferCache.java @@ -48,26 +48,20 @@ public class BufferCache { return buf; } - static void getBuffers( SmbComTransaction req, SmbComTransactionResponse rsp ) { + static void getBuffers( SmbComTransaction req, + SmbComTransactionResponse rsp ) throws InterruptedException { synchronized( cache ) { - try { - while ((freeBuffers + (MAX_BUFFERS - numBuffers)) < 2) { - cache.wait(); - } - req.txn_buf = getBuffer0(); - rsp.txn_buf = getBuffer0(); - } catch( InterruptedException ie ) { - ie.printStackTrace(); + while ((freeBuffers + (MAX_BUFFERS - numBuffers)) < 2) { + cache.wait(); } + req.txn_buf = getBuffer0(); + rsp.txn_buf = getBuffer0(); } } - static public byte[] getBuffer() { + static public byte[] getBuffer() throws InterruptedException { synchronized( cache ) { while ((freeBuffers + (MAX_BUFFERS - numBuffers)) < 1) { - try { - cache.wait(); - } catch(InterruptedException ie) { - } + cache.wait(); } return getBuffer0(); } diff --git a/src/jcifs/smb/Dfs.java b/src/jcifs/smb/Dfs.java index 825dc94..5f7700a 100644 --- a/src/jcifs/smb/Dfs.java +++ b/src/jcifs/smb/Dfs.java @@ -42,6 +42,7 @@ public class Dfs { static LogStream log = LogStream.getInstance(); static final boolean strictView = Config.getBoolean("jcifs.smb.client.dfs.strictView", false); static final long TTL = Config.getLong("jcifs.smb.client.dfs.ttl", 300); + static final boolean DISABLED = Config.getBoolean("jcifs.smb.client.dfs.disabled", false); protected static CacheEntry FALSE_ENTRY = new Dfs.CacheEntry(0L); @@ -49,6 +50,9 @@ public class Dfs { protected CacheEntry referrals = null; public HashMap getTrustedDomains(NtlmPasswordAuthentication auth) throws SmbAuthException { + if (DISABLED) + return null; + if (_domains != null && System.currentTimeMillis() > _domains.expiration) { _domains = null; } @@ -85,6 +89,9 @@ public class Dfs { } public SmbTransport getDc(String domain, NtlmPasswordAuthentication auth) throws SmbAuthException { + if (DISABLED) + return null; + try { UniAddress addr = UniAddress.getByName(domain, true); SmbTransport trans = SmbTransport.getSmbTransport(addr, 0); @@ -107,6 +114,9 @@ public class Dfs { String root, String path, NtlmPasswordAuthentication auth) throws SmbAuthException { + if (DISABLED) + return null; + try { String p = "\\" + domain + "\\" + root; if (path != null) @@ -130,7 +140,7 @@ public class Dfs { DfsReferral dr = null; long now = System.currentTimeMillis(); - if (root.equals("IPC$")) { + if (DISABLED || root.equals("IPC$")) { return null; } HashMap domains = getTrustedDomains(auth); @@ -217,6 +227,9 @@ public class Dfs { int s1, s2; String server, share, key; + if (DISABLED) + return; + s1 = path.indexOf('\\', 1); s2 = path.indexOf('\\', s1 + 1); server = path.substring(1, s1); diff --git a/src/jcifs/smb/NtTransQuerySecurityDescResponse.java b/src/jcifs/smb/NtTransQuerySecurityDescResponse.java index 3700805..31e2ec4 100644 --- a/src/jcifs/smb/NtTransQuerySecurityDescResponse.java +++ b/src/jcifs/smb/NtTransQuerySecurityDescResponse.java @@ -18,6 +18,8 @@ package jcifs.smb; +import java.io.IOException; + class NtTransQuerySecurityDescResponse extends SmbComNtTransactionResponse { SecurityDescriptor securityDescriptor; @@ -48,8 +50,12 @@ class NtTransQuerySecurityDescResponse extends SmbComNtTransactionResponse { if (errorCode != 0) return 4; - securityDescriptor = new SecurityDescriptor(); - bufferIndex += securityDescriptor.decode(buffer, bufferIndex, len); + try { + securityDescriptor = new SecurityDescriptor(); + bufferIndex += securityDescriptor.decode(buffer, bufferIndex, len); + } catch (IOException ioe) { + throw new RuntimeException(ioe.getMessage()); + } return bufferIndex - start; } diff --git a/src/jcifs/smb/SecurityDescriptor.java b/src/jcifs/smb/SecurityDescriptor.java index f40b86e..90e1261 100644 --- a/src/jcifs/smb/SecurityDescriptor.java +++ b/src/jcifs/smb/SecurityDescriptor.java @@ -27,10 +27,10 @@ public class SecurityDescriptor { public SecurityDescriptor() { } - public SecurityDescriptor(byte[] buffer, int bufferIndex, int len) { + public SecurityDescriptor(byte[] buffer, int bufferIndex, int len) throws IOException { this.decode(buffer, bufferIndex, len); } - public int decode(byte[] buffer, int bufferIndex, int len) { + public int decode(byte[] buffer, int bufferIndex, int len) throws IOException { int start = bufferIndex; bufferIndex++; // revision @@ -55,20 +55,28 @@ public class SecurityDescriptor { bufferIndex += 4; if (numAces > 4096) - throw new RuntimeException( "Invalid SecurityDescriptor" ); + throw new IOException( "Invalid SecurityDescriptor" ); - aces = new ACE[numAces]; - for (int i = 0; i < numAces; i++) { - aces[i] = new ACE(); - bufferIndex += aces[i].decode(buffer, bufferIndex); + if (daclOffset != 0) { + aces = new ACE[numAces]; + for (int i = 0; i < numAces; i++) { + aces[i] = new ACE(); + bufferIndex += aces[i].decode(buffer, bufferIndex); + } + } else { + aces = null; } return bufferIndex - start; } public String toString() { String ret = "SecurityDescriptor:\n"; - for (int ai = 0; ai < aces.length; ai++) { - ret += aces[ai].toString() + "\n"; + if (aces != null) { + for (int ai = 0; ai < aces.length; ai++) { + ret += aces[ai].toString() + "\n"; + } + } else { + ret += "NULL"; } return ret; } diff --git a/src/jcifs/smb/SmbFile.java b/src/jcifs/smb/SmbFile.java index 20ff7a9..3fe2650 100644 --- a/src/jcifs/smb/SmbFile.java +++ b/src/jcifs/smb/SmbFile.java @@ -2807,6 +2807,7 @@ if (this instanceof SmbNamedPipe) { /** * Return an array of Access Control Entry (ACE) objects representing * the security descriptor associated with this file or directory. + * If no DACL is present, null is returned. If the DACL is empty, an array with 0 elements is returned. * @param resolveSids Attempt to resolve the SIDs within each ACE form * their numeric representation to their corresponding account names. */ @@ -2830,13 +2831,15 @@ if (this instanceof SmbNamedPipe) { } aces = response.securityDescriptor.aces; - processAces(aces, resolveSids); + if (aces != null) + processAces(aces, resolveSids); return aces; } /** * Return an array of Access Control Entry (ACE) objects representing * the share permissions on the share exporting this file or directory. + * If no DACL is present, null is returned. If the DACL is empty, an array with 0 elements is returned. *

* Note that this is different from calling getSecurity on a * share. There are actually two different ACLs for shares - the ACL on @@ -2867,7 +2870,8 @@ if (this instanceof SmbNamedPipe) { if (rpc.retval != 0) throw new SmbException(rpc.retval, true); aces = rpc.getSecurity(); - processAces(aces, resolveSids); + if (aces != null) + processAces(aces, resolveSids); } finally { try { handle.close(); diff --git a/src/jcifs/smb/SmbFileInputStream.java b/src/jcifs/smb/SmbFileInputStream.java index bd75f90..a5157a3 100644 --- a/src/jcifs/smb/SmbFileInputStream.java +++ b/src/jcifs/smb/SmbFileInputStream.java @@ -23,6 +23,9 @@ import java.net.UnknownHostException; import java.net.MalformedURLException; import java.io.InputStream; import java.io.IOException; +import java.io.InterruptedIOException; + +import jcifs.util.transport.TransportException; /** * This InputStream can read bytes from a file on an SMB file server. Offsets are 64 bits. @@ -76,6 +79,20 @@ public class SmbFileInputStream extends InputStream { file.tree.session.transport.server.maxBufferSize - 70 ); } + protected IOException seToIoe(SmbException se) { + IOException ioe = se; + Throwable root = se.getRootCause(); + if (root instanceof TransportException) { + ioe = (TransportException)root; + root = ((TransportException)ioe).getRootCause(); + } + if (root instanceof InterruptedException) { + ioe = new InterruptedIOException(root.getMessage()); + ioe.initCause(root); + } + return ioe; + } + /** * Closes this input stream and releases any system resources associated with the stream. * @@ -83,8 +100,12 @@ public class SmbFileInputStream extends InputStream { */ public void close() throws IOException { - file.close(); - tmp = null; + try { + file.close(); + tmp = null; + } catch (SmbException se) { + throw seToIoe(se); + } } /** @@ -163,7 +184,7 @@ if( file.type == SmbFile.TYPE_NAMED_PIPE ) { se.getNtStatus() == NtStatus.NT_STATUS_PIPE_BROKEN ) { return -1; } - throw se; + throw seToIoe(se); } if(( n = response.dataLength ) <= 0 ) { return (int)((fp - start) > 0L ? fp - start : -1); @@ -191,19 +212,23 @@ if( file.type == SmbFile.TYPE_NAMED_PIPE ) { return 0; } - pipe = (SmbNamedPipe)file; - file.open(SmbFile.O_EXCL, pipe.pipeType & 0xFF0000, SmbFile.ATTR_NORMAL, 0 ); - - req = new TransPeekNamedPipe( file.unc, file.fid ); - resp = new TransPeekNamedPipeResponse( pipe ); - - pipe.send( req, resp ); - if( resp.status == TransPeekNamedPipeResponse.STATUS_DISCONNECTED || - resp.status == TransPeekNamedPipeResponse.STATUS_SERVER_END_CLOSED ) { - file.opened = false; - return 0; + try { + pipe = (SmbNamedPipe)file; + file.open(SmbFile.O_EXCL, pipe.pipeType & 0xFF0000, SmbFile.ATTR_NORMAL, 0 ); + + req = new TransPeekNamedPipe( file.unc, file.fid ); + resp = new TransPeekNamedPipeResponse( pipe ); + + pipe.send( req, resp ); + if( resp.status == TransPeekNamedPipeResponse.STATUS_DISCONNECTED || + resp.status == TransPeekNamedPipeResponse.STATUS_SERVER_END_CLOSED ) { + file.opened = false; + return 0; + } + return resp.available; + } catch (SmbException se) { + throw seToIoe(se); } - return resp.available; } /** * Skip n bytes of data on this stream. This operation will not result diff --git a/src/jcifs/smb/SmbSession.java b/src/jcifs/smb/SmbSession.java index 0be7059..67551d0 100644 --- a/src/jcifs/smb/SmbSession.java +++ b/src/jcifs/smb/SmbSession.java @@ -236,7 +236,15 @@ do { } request.uid = uid; request.auth = auth; - transport.send( request, response ); + try { + transport.send( request, response ); + } catch (SmbException se) { + if (request instanceof SmbComTreeConnectAndX) { + logoff(true); + } + request.digest = null; + throw se; + } } } void sessionSetup( ServerMessageBlock andx, diff --git a/src/jcifs/smb/SmbTransport.java b/src/jcifs/smb/SmbTransport.java index 270ef07..e49853a 100644 --- a/src/jcifs/smb/SmbTransport.java +++ b/src/jcifs/smb/SmbTransport.java @@ -182,8 +182,6 @@ public class SmbTransport extends Transport implements SmbConstants { } else { socket = new Socket( address.getHostAddress(), 139, localAddr, localPort ); } -jcifs.Config.socketCount++; -log.println(jcifs.Config.socketCount + ": new Socket: " + socket); socket.setSoTimeout( SO_TIMEOUT ); out = socket.getOutputStream(); in = socket.getInputStream(); @@ -193,13 +191,8 @@ log.println(jcifs.Config.socketCount + ": new Socket: " + socket); out.write( sbuf, 0, ssp.writeWireFormat( sbuf, 0 )); if (readn( in, sbuf, 0, 4 ) < 4) { try { -String s = socket.toString(); socket.close(); -jcifs.Config.socketCount--; -log.println(jcifs.Config.socketCount + ": socket closed: " + s); } catch(IOException ioe) { -log.println(jcifs.Config.socketCount + ": socket close exception:"); -ioe.printStackTrace(log); } throw new SmbException( "EOF during NetBIOS session request" ); } @@ -213,10 +206,7 @@ ioe.printStackTrace(log); switch (errorCode) { case NbtException.CALLED_NOT_PRESENT: case NbtException.NOT_LISTENING_CALLED: -String s = socket.toString(); socket.close(); -jcifs.Config.socketCount--; -log.println(jcifs.Config.socketCount + ": socket closed: " + s); break; default: disconnect( true ); @@ -259,8 +249,6 @@ log.println(jcifs.Config.socketCount + ": socket closed: " + s); } else { socket = new Socket( address.getHostAddress(), port, localAddr, localPort ); } -jcifs.Config.socketCount++; -log.println(jcifs.Config.socketCount + ": new Socket: " + socket); socket.setSoTimeout( SO_TIMEOUT ); out = socket.getOutputStream(); in = socket.getInputStream(); @@ -361,10 +349,7 @@ log.println(jcifs.Config.socketCount + ": new Socket: " + socket); socket.shutdownOutput(); out.close(); in.close(); -String s = socket.toString(); socket.close(); -jcifs.Config.socketCount--; -log.println(jcifs.Config.socketCount + ": socket closed: " + s); digest = null; } @@ -635,6 +620,8 @@ log.println(jcifs.Config.socketCount + ": socket closed: " + s); } } catch( SmbException se ) { throw se; + } catch( InterruptedException ie ) { + throw new SmbException( ie.getMessage(), ie ); } catch( IOException ioe ) { throw new SmbException( ioe.getMessage(), ioe ); }