+Wed Sep 21 01:53:28 EDT 2005
+jcifs-1.2.4 released / Timeout Transport Exception, Bogus Signature Error,
+ and More
+
+A NetBIOS keep-alive message (received after ~10 minutes) would break
+message processesing with a timedout waiting for response Exception. This
+has been fixed.
+
+JCIFS would fail to validate responses with a status that is not zero.
+Assuming we are calculating the verfication signature correctly I can only
+assume the affected servers choose not to generate the correct signature
+for error responses (perhaps for DOS reasons). Because JCIFS checked the
+signature before the message status, an error response would fail with
+"signature verification failure". This behavior has been changed so that
+signatures are not verified if the status is non zero.
+
+It was discovered that the new transport (as of 1.2.x) could not cleanly
+recover from temporary server failure (e.g. a restart). This has been
+fixed. Methods will still throw Exceptions but moment the server comes back
+online the client gracefully recover.
+
+Wed Aug 24 13:29:44 EDT 2005
+jcifs-1.2.3 released / Port 445 Fixed
+
+A mistake in the 1.2.2 release broke port 445 communication entirely. It
+has been fixed. The exact error (with a sufficiently high loglevel) was
+"Invalid payload size: 1".
+
+Sat Aug 20 00:26:11 EDT 2005
+jcifs-1.2.2 released / Exception "cannot assign requested address" Fixed,
+ Clusters, NetApp Filer, and More
+
+There have been a number of small fixes. These are:
+
+o The "cannot assign requested address" exception caused by trying to bind
+ the local address 127.0.0.1 has been fixed.
+o In a cluster environment the NTLM HTTP Filter could fail with "account
+ currently disabled" or "Access denied" errors due to a deserialization
+ issue of "preauthentication" credentials stored in the HttpSession. The
+ initialization of default credentials has been changed however it is not
+ clear that the change will have any effect as I do not have a clustered
+ environment in which to test.
+o The combination of plain text passwords and Unicode (largely specific to
+ Samba 3) has been fixed.
+o A bogus debugging statement has been discovered and removed. Who left that
+ in there?!
+o A Socket.shutdownOutput() call has been added to doDisconnect as it is
+ believed to reduce spurrious RST frames observed when abruptly shutting
+ down transports. These are believed to be harmless but they have been
+ associated with unsightly messages in Samba log files.
+o The copyTo() method will now check to see if the source path is a child,
+ parent or equal to the destination path and if so throw a Source and
+ destination paths overlap exception.
+o An additional debugging statement has been added to the NTLM HTTP Filter
+ domain controller interrogation code.
+o The getDiskFreeSpace call could fail with NetApp Filer. It has been
+ repaired.
+
Sun Jul 3 23:33:03 EDT 2005
jcifs-1.2.1 released
<project name="jcifs" default="usage" basedir=".">
- <property name="version" value="1.2.1"/>
- <property name="reldate" value="Jul 4, 2005"/>
+ <property name="version" value="1.2.4"/>
+ <property name="reldate" value="Sep 21, 2005"/>
<target name="usage">
<echo>
}
public static InetAddress getLocalHost() {
String addr = prp.getProperty( "jcifs.smb.client.laddr" );
- try {
- if( addr == null ) {
- return InetAddress.getLocalHost();
- }
- return InetAddress.getByName( addr );
- } catch( UnknownHostException uhe ) {
- if( log.level > 0 ) {
- log.println( addr );
- uhe.printStackTrace( log );
+
+ if (addr != null) {
+ try {
+ return InetAddress.getByName( addr );
+ } catch( UnknownHostException uhe ) {
+ if( log.level > 0 ) {
+ log.println( "Ignoring jcifs.smb.client.laddr address: " + addr );
+ uhe.printStackTrace( log );
+ }
}
}
public static final int NT_STATUS_FILE_IS_A_DIRECTORY = 0xC00000ba;
public static final int NT_STATUS_DUPLICATE_NAME = 0xC00000bd;
public static final int NT_STATUS_NETWORK_NAME_DELETED = 0xC00000c9;
+ public static final int NT_STATUS_NETWORK_ACCESS_DENIED = 0xC00000ca;
public static final int NT_STATUS_BAD_NETWORK_NAME = 0xC00000cc;
public static final int NT_STATUS_NOT_A_DIRECTORY = 0xC0000103;
public static final int NT_STATUS_CANNOT_DELETE = 0xC0000121;
public static final int NT_STATUS_PIPE_BROKEN = 0xC000014b;
public static final int NT_STATUS_LOGON_TYPE_NOT_GRANTED = 0xC000015b;
public static final int NT_STATUS_TRUSTED_DOMAIN_FAILURE = 0xC000018c;
+ public static final int NT_STATUS_NOT_FOUND = 0xC0000225;
public static final int NT_STATUS_ACCOUNT_LOCKED_OUT = 0xC0000234;
public static final int NT_STATUS_PATH_NOT_COVERED = 0xC0000257;
NT_STATUS_FILE_IS_A_DIRECTORY,
NT_STATUS_DUPLICATE_NAME,
NT_STATUS_NETWORK_NAME_DELETED,
+ NT_STATUS_NETWORK_ACCESS_DENIED,
NT_STATUS_BAD_NETWORK_NAME,
NT_STATUS_NOT_A_DIRECTORY,
NT_STATUS_CANNOT_DELETE,
NT_STATUS_PIPE_BROKEN,
NT_STATUS_LOGON_TYPE_NOT_GRANTED,
NT_STATUS_TRUSTED_DOMAIN_FAILURE,
+ NT_STATUS_NOT_FOUND,
NT_STATUS_ACCOUNT_LOCKED_OUT,
NT_STATUS_PATH_NOT_COVERED,
};
"Access is denied.",
"A duplicate name exists on the network.",
"The specified network name is no longer available.",
+ "Network access is denied.",
"The network name cannot be found.",
"The directory name is invalid.",
"Access is denied.",
"The pipe has been ended.",
"Logon failure: the user has not been granted the requested logon type at this computer.",
"The trust relationship between the primary domain and the trusted domain failed.",
+ "NT_STATUS_NOT_FOUND",
"The referenced account is currently locked out and may not be logged on to.",
"The remote system is not reachable by the transport.",
};
private static final int LM_COMPATIBILITY =
Config.getInt("jcifs.smb.lmCompatibility", 0);
- static final String DEFAULT_DOMAIN =
- Config.getProperty("jcifs.smb.client.domain", "?");
-
- private static final String DEFAULT_USERNAME =
- Config.getProperty("jcifs.smb.client.username", "GUEST");
-
- static final String BLANK = "";
- static final String DEFAULT_PASSWORD =
- Config.getProperty("jcifs.smb.client.password", BLANK);
-
private static final Random RANDOM = new Random();
private static LogStream log = LogStream.getInstance();
System.arraycopy( e8, 0, e, i * 8, 8 );
}
}
+
+ static String DEFAULT_DOMAIN;
+ static String DEFAULT_USERNAME;
+ static String DEFAULT_PASSWORD;
+ static final String BLANK = "";
+
+ static void initDefaults() {
+ if (DEFAULT_DOMAIN != null) return;
+ DEFAULT_DOMAIN = Config.getProperty("jcifs.smb.client.domain", "?");
+ DEFAULT_USERNAME = Config.getProperty("jcifs.smb.client.username", "GUEST");
+ DEFAULT_PASSWORD = Config.getProperty("jcifs.smb.client.password", BLANK);
+ }
+
/**
* Generate the ANSI DES hash for the password associated with these credentials.
*/
username = userInfo.substring( u, i );
}
+ initDefaults();
+
if( domain == null ) this.domain = DEFAULT_DOMAIN;
if( username == null ) this.username = DEFAULT_USERNAME;
if( password == null ) this.password = DEFAULT_PASSWORD;
this.domain = domain;
this.username = username;
this.password = password;
+
+ initDefaults();
+
if( domain == null ) this.domain = DEFAULT_DOMAIN;
if( username == null ) this.username = DEFAULT_USERNAME;
if( password == null ) this.password = DEFAULT_PASSWORD;
}
void reset() {
+ flags = (byte)( FLAGS_PATH_NAMES_CASELESS | FLAGS_PATH_NAMES_CANONICALIZED );
+ flags2 = 0;
+ errorCode = 0;
+ received = false;
}
int writeString( String str, byte[] dst, int dstIndex ) {
return writeString( str, dst, dstIndex, useUnicode );
class SmbComDelete extends ServerMessageBlock {
private int searchAttributes;
- private String fileName;
SmbComDelete( String fileName ) {
- this.fileName = fileName;
+ this.path = fileName;
command = SMB_COM_DELETE;
searchAttributes = ATTR_HIDDEN | ATTR_HIDDEN | ATTR_SYSTEM;
}
int start = dstIndex;
dst[dstIndex++] = (byte)0x04;
- dstIndex += writeString( fileName, dst, dstIndex );
+ dstIndex += writeString( path, dst, dstIndex );
return dstIndex - start;
}
return new String( "SmbComDelete[" +
super.toString() +
",searchAttributes=0x" + Hexdump.toHexString( searchAttributes, 4 ) +
- ",fileName=" + fileName + "]" );
+ ",fileName=" + path + "]" );
}
}
( auth.hashesExternal || auth.password.length() > 0 )) {
System.arraycopy( accountPassword, 0, dst, dstIndex, passwordLength );
dstIndex += passwordLength;
+ if (session.transport.server.encryptedPasswords == false && useUnicode) {
+ /* Align Unicode plain text password manually
+ */
+ if ((( dstIndex - headerStart ) % 2 ) != 0 ) {
+ dst[dstIndex++] = (byte)'\0';
+ }
+ }
System.arraycopy( unicodePassword, 0, dst, dstIndex, unicodePasswordLength );
dstIndex += unicodePasswordLength;
}
- if( useUnicode ) {
- // at least NT 4 observed needing this only with unicode
- dst[dstIndex++] = (byte)'\0';
- }
dstIndex += writeString( accountName, dst, dstIndex );
dstIndex += writeString( primaryDomain, dst, dstIndex );
}
void reset() {
+ super.reset();
isPrimary = hasMore = true;
}
void reset( int key, String lastName ) {
}
void reset() {
+ super.reset();
bufDataStart = 0;
isPrimary = hasMore = true;
parametersDone = dataDone = false;
- received = false;
}
public boolean hasMoreElements() {
return errorCode == 0 && hasMore;
trans = SmbTransport.getSmbTransport( addr, url.getPort() );
tree = trans.getSmbSession( auth ).getSmbTree( dr.share, null );
- unc = request.path = dr.nodepath + unc.substring( dr.path.length() );
+ unc = dr.nodepath + unc.substring( dr.path.length() );
if( request.path.charAt( request.path.length() - 1 ) == '\\' ) {
- request.path = unc + '\\';
+ request.path = unc + '\\'; /* preserve trailing slash */
} else {
request.path = unc;
}
NbtAddress.MASTER_BROWSER_NAME, 0x01, null);
return UniAddress.getByName( addr.getHostAddress() );
} catch( UnknownHostException uhe ) {
+ NtlmPasswordAuthentication.initDefaults();
if( NtlmPasswordAuthentication.DEFAULT_DOMAIN.equals( "?" )) {
throw uhe;
}
if( dfsReferral == null ) {
return null;
}
- return "smb:/" + (new String( dfsReferral.node + unc )).replace( '\\', '/' );
+ String path = "smb:/" + (new String( dfsReferral.node + unc )).replace( '\\', '/' );
+ if (isDirectory()) {
+ path += '/';
+ }
+ return path;
}
/**
if( name.length() > 0 ) {
SmbFile f = new SmbFile( this, name, TYPE_FILESYSTEM,
e.getAttributes(), e.createTime(), e.lastModified(), e.length() );
-System.out.print(" " + name );
if( ff != null && ff.accept( f ) == false ) {
continue;
}
dest.exists();
}
+ /* It is invalid for the source path to be a child of the destination
+ * path or visa versa.
+ */
+ try {
+ if (getAddress().equals( dest.getAddress() ) &&
+ canon.regionMatches( true, 0, dest.canon, 0,
+ Math.min( canon.length(), dest.canon.length() ))) {
+ throw new SmbException( "Source and destination paths overlap." );
+ }
+ } catch (UnknownHostException uhe) {
+ }
+
w = new WriterThread();
w.setDaemon( true );
w.start();
try {
return queryFSInformation(level);
} catch( SmbException ex ) {
- if(ex.getNtStatus() == NtStatus.NT_STATUS_INVALID_INFO_CLASS) {
- // SMB_FS_FULL_SIZE_INFORMATION not supported by the server.
- level = Trans2QueryFSInformationResponse.SMB_INFO_ALLOCATION;
- return queryFSInformation(level);
+ switch (ex.getNtStatus()) {
+ case NtStatus.NT_STATUS_INVALID_INFO_CLASS:
+ case NtStatus.NT_STATUS_UNSUCCESSFUL: // NetApp Filer
+ // SMB_FS_FULL_SIZE_INFORMATION not supported by the server.
+ level = Trans2QueryFSInformationResponse.SMB_INFO_ALLOCATION;
+ return queryFSInformation(level);
}
throw ex;
}
try {
return interrogate( dc_list[i] );
} catch (SmbException se) {
- if (SmbTransport.log.level > 1)
- SmbTransport.log.println( "Failed validate DC: " + dc_list[i] +
- ": " + se.getMessage() );
+ if (SmbTransport.log.level > 1) {
+ SmbTransport.log.println( "Failed validate DC: " + dc_list[i] );
+ if (SmbTransport.log.level > 2)
+ se.printStackTrace( SmbTransport.log );
+ }
}
dc_list[i] = null;
}
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;
- InetAddress la1 = localAddr == null ? LADDR : localAddr;
- InetAddress la2 = this.localAddr == null ? LADDR : this.localAddr;
return address.equals( this.address ) &&
p1 == p2 &&
- la1.equals( la2 ) &&
+ (localAddr == this.localAddr ||
+ (localAddr != null &&
+ localAddr.equals( this.localAddr ))) &&
localPort == this.localPort;
}
boolean hasCapability( int cap ) throws SmbException {
void ssn139() throws IOException {
Name calledName = new Name( address.firstCalledName(), 0x20, null );
do {
- socket = new Socket( address.getHostAddress(), 139, localAddr, localPort );
+ if (localAddr == null) {
+ socket = new Socket( address.getHostAddress(), 139 );
+ } else {
+ socket = new Socket( address.getHostAddress(), 139, localAddr, localPort );
+ }
socket.setSoTimeout( SO_TIMEOUT );
out = socket.getOutputStream();
in = socket.getInputStream();
if (port == 139) {
ssn139();
} else {
- socket = new Socket( address.getHostAddress(), port, localAddr, localPort );
+ if (localAddr == null) {
+ socket = new Socket( address.getHostAddress(), port );
+ } else {
+ socket = new Socket( address.getHostAddress(), port, localAddr, localPort );
+ }
socket.setSoTimeout( SO_TIMEOUT );
out = socket.getOutputStream();
in = socket.getInputStream();
ssn.logoff( hard );
iter.remove();
}
+ socket.shutdownOutput();
out.close();
in.close();
socket.close();
int n;
do {
n = readn( in, sbuf, 0, 4 );
- } while (sbuf[0] == 0x85); /* Dodge NetBIOS keep-alive */
- /* read smb header */
+ } while (sbuf[0] == (byte)0x85); /* Dodge NetBIOS keep-alive */
+ /* read smb header */
if ((n = readn( in, sbuf, 4, 32 )) < 32) {
return null; /* stream closed */
}
}
/* out of phase maybe? */
/* inch forward 1 byte and try again */
- for (int i = 0; i < 7; i++) {
+ for (int i = 0; i < 35; i++) {
sbuf[i] = sbuf[i + 1];
}
int b;
- if ((b = in.read()) == 0) return null;
- sbuf[7] = (byte)b;
+ if ((b = in.read()) == -1) return null;
+ sbuf[35] = (byte)b;
}
key.mid = Encdec.dec_uint16le( sbuf, 34 );
out.write( BUF, 0, 4 + n );
}
}
+ protected void doSend0( Request request ) throws IOException {
+ try {
+ doSend( request );
+ } catch( IOException ioe ) {
+ if (log.level > 2)
+ ioe.printStackTrace( log );
+ try {
+ disconnect( true );
+ } catch( IOException ioe2 ) {
+ ioe2.printStackTrace( log );
+ }
+ throw ioe;
+ }
+ }
protected void doRecv( Response response ) throws IOException {
ServerMessageBlock resp = (ServerMessageBlock)response;
}
}
- if (digest != null) {
+ /* Verification fails (w/ W2K3 server at least) if status is not 0. This
+ * suggests MS doesn't compute the signature (correctly) for error responses
+ * (perhaps for DOS reasons).
+ */
+ if (digest != null && resp.errorCode == 0) {
digest.verify( BUF, 4, resp );
}
}
try {
if (response == null) {
- doSend( request );
+ doSend0( request );
return;
} else if (request instanceof SmbComTransaction) {
response.command = request.command;
*/
do {
- doSend( req );
+ doSend0( req );
} while( req.hasMoreElements() && req.nextElement() != null );
/*
case ServerMessageBlock.SMB_COM_TREE_DISCONNECT:
break;
case ServerMessageBlock.SMB_COM_TRANSACTION:
+ case ServerMessageBlock.SMB_COM_TRANSACTION2:
switch( ((SmbComTransaction)request).subCommand & 0xFF ) {
case SmbComTransaction.NET_SHARE_ENUM:
case SmbComTransaction.NET_SERVER_ENUM2:
}
break;
default:
- throw new SmbException( "Invalid operation for " + service + " service" );
+ throw new SmbException( "Invalid operation for " + service + " service" + request );
}
}
request.tid = tid;
if( inDfs && request.path != null && request.path.length() > 0 ) {
+ /* When DFS is in action all request paths are
+ * full UNC paths minus the first backslash like
+ * \server\share\path\to\file
+ * as opposed to normally
+ * \path\to\file
+ */
request.flags2 = ServerMessageBlock.FLAGS2_RESOLVE_PATHS_IN_DFS;
request.path = '\\' + session.transport().tconHostName + '\\' + share + request.path;
}
request );
}
}
+ } catch( IOException ioe ) {
+ if (log.level > 2)
+ ioe.printStackTrace( log );
+ try {
+ disconnect( true );
+ } catch( IOException ioe2 ) {
+ ioe2.printStackTrace( log );
+ }
+ throw ioe;
} catch( InterruptedException ie ) {
throw new TransportException( ie );
} finally {