+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.
<project name="jcifs" default="usage" basedir=".">
- <property name="version" value="1.2.21"/>
- <property name="reldate" value="May 28, 2008"/>
+ <property name="version" value="1.2.22"/>
+ <property name="reldate" value="Jun 25, 2008"/>
<target name="usage">
<echo>
+import java.io.InterruptedIOException;
import jcifs.util.transport.TransportException;
import jcifs.smb.*;
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);
}
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;
}
}
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();
}
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
$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}/
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;
package jcifs.dcerpc.msrpc;
+import java.io.IOException;
+
import jcifs.smb.*;
import jcifs.util.Hexdump;
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;
}
}
import java.net.*;
import java.io.IOException;
-import java.io.InterruptedIOException;
import java.util.HashMap;
import java.util.StringTokenizer;
import jcifs.Config;
// 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();
*/
if( socket != null ) {
-String s = socket.toString();
socket.close();
-jcifs.Config.socketCount--;
-log.println(jcifs.Config.socketCount + ": socket closed: " + s);
socket = null;
}
thread = null;
}
} catch( InterruptedException ie ) {
+ throw new IOException(ie.getMessage());
} finally {
responseTable.remove( nid );
}
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();
}
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);
protected CacheEntry referrals = null;
public HashMap getTrustedDomains(NtlmPasswordAuthentication auth) throws SmbAuthException {
+ if (DISABLED)
+ return null;
+
if (_domains != null && System.currentTimeMillis() > _domains.expiration) {
_domains = null;
}
}
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);
String root,
String path,
NtlmPasswordAuthentication auth) throws SmbAuthException {
+ if (DISABLED)
+ return null;
+
try {
String p = "\\" + domain + "\\" + root;
if (path != null)
DfsReferral dr = null;
long now = System.currentTimeMillis();
- if (root.equals("IPC$")) {
+ if (DISABLED || root.equals("IPC$")) {
return null;
}
HashMap domains = getTrustedDomains(auth);
int s1, s2;
String server, share, key;
+ if (DISABLED)
+ return;
+
s1 = path.indexOf('\\', 1);
s2 = path.indexOf('\\', s1 + 1);
server = path.substring(1, s1);
package jcifs.smb;
+import java.io.IOException;
+
class NtTransQuerySecurityDescResponse extends SmbComNtTransactionResponse {
SecurityDescriptor securityDescriptor;
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;
}
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
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;
}
/**
* 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.
*/
}
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.
* <p>
* Note that this is different from calling <tt>getSecurity</tt> on a
* share. There are actually two different ACLs for shares - the ACL on
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();
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.
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.
*
*/
public void close() throws IOException {
- file.close();
- tmp = null;
+ try {
+ file.close();
+ tmp = null;
+ } catch (SmbException se) {
+ throw seToIoe(se);
+ }
}
/**
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);
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
}
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,
} 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();
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" );
}
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 );
} 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();
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;
}
}
} catch( SmbException se ) {
throw se;
+ } catch( InterruptedException ie ) {
+ throw new SmbException( ie.getMessage(), ie );
} catch( IOException ioe ) {
throw new SmbException( ioe.getMessage(), ioe );
}