+Sun Apr 6 19:46:47 EDT 2008
+jcifs-1.2.19 released
+
+This release adds proper support for domain based DFS roots that are not
+hosted on domain controllers and eliminates the now-obsolete behavior of
+building a merged list of shares across hosts. A new NetrDfsEnumEx RPC
+is used to enumerate DFS roots when listing shares. The equals methods
+for SmbFile and UniAddress could return true even though the files were
+not equal. That issue has been fixed. Some SmbComOpenAndX parameters
+were incorrectly swapped which would cause failure on Windows 98.
+
Mon Feb 18 23:02:02 EST 2008
jcifs-1.2.18 released
<project name="jcifs" default="usage" basedir=".">
- <property name="version" value="1.2.18"/>
- <property name="reldate" value="Feb 18, 2008"/>
+ <property name="version" value="1.2.19"/>
+ <property name="reldate" value="Apr 6, 2008"/>
<target name="usage">
<echo>
+++ /dev/null
-C:\tmp>ktpass /princ HTTP/www.foo.net@WIN.NET /ptype KRB5_NT_PRINCIPAL /desonly /pass asj7j112233hh4455 /mapuser test2\r
-Targeting domain controller: ts0.win.net\r
-Using legacy password setting method\r
-Successfully mapped HTTP/www.foo.net to test2.\r
-Key created.\r
-Account test2 has been set for DES-only encryption.
\ No newline at end of file
msg = new String( "this is msg #" + i ).getBytes();
out.write( msg );
System.out.write( msg );
- Thread.sleep( 17000 );
-out = new SmbFileOutputStream( f, true );
+ Thread.sleep( 10000 );
+//out = new SmbFileOutputStream( f, true );
}
out.close();
--- /dev/null
+import java.util.*;
+import javax.naming.*;
+import javax.naming.directory.*;
+
+public class DnsSrv {
+
+ String getDomain(String name) throws NamingException {
+ DirContext context;
+ NameNotFoundException ret = null;
+
+ context = new InitialDirContext();
+ for ( ;; ) {
+ try {
+ Attributes attributes = context.getAttributes(
+ "dns:/_ldap._tcp.dc._msdcs." + name,
+ new String[] { "SRV" }
+ );
+ return name;
+ } catch (NameNotFoundException nnfe) {
+ ret = nnfe;
+ }
+ int dot = name.indexOf('.');
+ if (dot == -1)
+ break;
+ name = name.substring(dot + 1);
+ }
+
+ throw ret != null ? ret : new NamingException("invalid name");
+ }
+
+ public static void main(String argv[]) throws Exception {
+ DnsSrv dnsSrv = new DnsSrv();
+ System.out.println(dnsSrv.getDomain(argv[0]));
+ }
+}
+
--- /dev/null
+/* Test the following file operations:
+ *
+ * canRead
+ * false - a target that is already open by another process
+ * false - the target does not exist
+ * true - the file exists and there are no sharing issues
+ * canWrite
+ * true - the file exists and there are no sharing issues
+ * false - the file is marked read-only
+ * false - the file does not exist
+ * delete
+ * true - the file existed and was succcessfully deleted
+ * false - the target did not exist
+ * false - the target is a share, server, workgroup or similar
+ * false - the target or file under the target directory failed was read-only
+ * exists
+ * true - the target, share, IPC share, named pipe, server, or workgroup exists
+ * false - the opposite of the above
+ * isDirectory
+ * true - the target is a workgroup, server, share, or directory
+ * false - the target is not one of the above or does not exist
+ * isFile
+ * direct opposite of isDirectory
+ * isHidden
+ * true - target is share ending in $ or marked as hidden
+ * length
+ * the file was created to be no larger than ~2G and reports back the size specified
+ * mkdir
+ * true - a directory was created successfuly
+ * false - the directory could not be created
+ * renameTo
+ * true - the target was renamed
+ */
+
+import jcifs.smb.*;
+import java.io.IOException;
+import java.util.Date;
+
+public class FileOpsRenameTo {
+
+ static final int ATTR_ALL = SmbFile.ATTR_ARCHIVE | SmbFile.ATTR_HIDDEN | SmbFile.ATTR_READONLY | SmbFile.ATTR_SYSTEM;
+
+ public static void main( String argv[] ) throws Exception {
+
+ if( argv.length != 1 ) {
+ System.out.println( "Must provide an SMB URL of a remote location on which tests will be conducted." );
+ System.exit( 1 );
+ }
+
+ SmbFile s = new SmbFile( argv[0] );
+ SmbFile d = new SmbFile( s, "JcifsTestOpsDir/" );
+
+ // Create a file to test against
+
+ SmbFile f = null;
+ try {
+ f = new SmbFile( d, "foo.txt" );
+ SmbFileOutputStream o = new SmbFileOutputStream( f );
+ o.write( "The Common Internet File System (CIFS) is the de-facto file sharing protocol on the Microsoft Windows platform. It is the underlying networking protocol used when accessing shares with Windows Explorer, the Network Neighborhood, via a Map Network Drive... dialog, the C:\\> net use * \\\\server\\share commands, or smbclient on UNIX, smbfs on Linux, and elsewhere.\r\n".getBytes() );
+ o.close();
+ } catch( IOException ioe ) {
+ System.out.println( "fail - could not create file " + d + "foo.txt: " + ioe.getMessage() );
+ }
+ System.out.println( "okay - created file " + d + "foo.txt" );
+
+ // renameTo - rename the file to bar.txt
+
+ SmbFile b = new SmbFile( d, "bar.txt" );
+
+ try {
+ f.renameTo( b );
+ System.out.println( "okay - renameTo " + f + " to " + b + " successful even with read-only" );
+ try {
+ b.renameTo(f);
+ } catch( SmbException se ) {
+ System.out.println( "fail - but failed to rename file back to original!" );
+ throw se;
+ }
+ } catch( SmbException se ) {
+ se.printStackTrace();
+ }
+
+ }
+}
+
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++) {
Thread.sleep(200);
it.interrupt();
public static void main( String[] argv ) throws Exception {
- SmbFile file = new SmbFile( argv[0] );
+ for (int a = 0; a < argv.length; a++) {
+ SmbFile file;
+ SmbFile[] files = new SmbFile[0];
- long t1 = System.currentTimeMillis();
- SmbFile[] files = file.listFiles();
- long t2 = System.currentTimeMillis() - t1;
+ file = new SmbFile( argv[a] );
- for( int i = 0; i < files.length; i++ ) {
- System.out.print( " " + files[i].getName() );
+ long t1 = System.currentTimeMillis();
+ try {
+ files = file.listFiles();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ long t2 = System.currentTimeMillis() - t1;
+
+ for( int i = 0; i < files.length; i++ ) {
+ System.out.print( " " + files[i].getName() );
+ }
+ System.out.println();
+ System.out.println( files.length + " files in " + t2 + "ms" );
}
- System.out.println();
- System.out.println( files.length + " files in " + t2 + "ms" );
}
}
while(( n = in.read( b )) > 0 ) {
System.out.write( b, 0, n );
tot += n;
- Thread.sleep( 17000 );
+ Thread.sleep( 10000 );
}
in.close();
JAVA_HOME=/usr/local/java
CLASSPATH=../build:.
-PROPERTIES=../../user10.prp
+PROPERTIES=../../user1.prp
RUN="${JAVA_HOME}/bin/java -cp ${CLASSPATH} -Djcifs.properties=${PROPERTIES}"
SERVER=dc1.w.net
-SHARE=tmp
+SHARE=target1
WRITE_DIR=test/
SRC_DIR=test/Junk
FILE1=test/Junk/10883563.doc
import jcifs.netbios.NbtAddress;
import jcifs.netbios.Lmhosts;
import jcifs.util.LogStream;
+import javax.naming.*;
+import javax.naming.directory.*;
/**
* <p>Under normal conditions it is not necessary to use
throw new UnknownHostException( hostname );
}
+ /**
+ * Perform DNS SRV lookup on successively shorter suffixes of name
+ * and return successful suffix or throw an UnknownHostException.
+ public static String getDomainByName(String name) throws UnknownHostException {
+ DirContext context;
+ UnknownHostException uhe = null;
+
+ try {
+ context = new InitialDirContext();
+ for ( ;; ) {
+ try {
+ Attributes attributes = context.getAttributes(
+ "dns:/_ldap._tcp.dc._msdcs." + name,
+ new String[] { "SRV" }
+ );
+ return name;
+ } catch (NameNotFoundException nnfe) {
+ uhe = new UnknownHostException(nnfe.getMessage());
+ }
+ int dot = name.indexOf('.');
+ if (dot == -1)
+ break;
+ name = name.substring(dot + 1);
+ }
+ } catch (NamingException ne) {
+ if (log.level > 1)
+ ne.printStackTrace(log);
+ }
+
+ throw uhe != null ? uhe : new UnknownHostException("invalid name");
+ }
+ */
+
+
Object addr;
String calledName;
/**
* Compare two addresses for equality. Two <tt>UniAddress</tt>s are equal
- * if they are both <tt>UniAddress' and refer to the same IP address.
+ * if they are both <tt>UniAddress</tt>' and refer to the same IP address.
*/
-
+ public boolean equals( Object obj ) {
+ return obj instanceof UniAddress && addr.equals(((UniAddress)obj).addr);
+ }
+/*
public boolean equals( Object obj ) {
return obj instanceof UniAddress && addr.hashCode() == obj.hashCode();
}
+*/
/**
* Guess first called name to try for session establishment. This
INTERFACES.put("srvsvc", srvsvc.getSyntax());
INTERFACES.put("lsarpc", lsarpc.getSyntax());
INTERFACES.put("samr", samr.getSyntax());
+ INTERFACES.put("netdfs", netdfs.getSyntax());
}
String proto;
--- /dev/null
+/* jcifs msrpc client library in Java
+ * Copyright (C) 2008 "Michael B. Allen" <jcifs at samba dot org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package jcifs.dcerpc.msrpc;
+
+import jcifs.smb.*;
+import jcifs.dcerpc.ndr.*;
+
+public class MsrpcDfsRootEnum extends netdfs.NetrDfsEnumEx {
+
+ public MsrpcDfsRootEnum(String server) {
+ super(server, 200, 0xFFFF, new netdfs.DfsEnumStruct(), new NdrLong(0));
+ info.level = level;
+ info.e = new netdfs.DfsEnumArray200();
+ ptype = 0;
+ flags = DCERPC_FIRST_FRAG | DCERPC_LAST_FRAG;
+ }
+
+ public FileEntry[] getEntries() {
+ netdfs.DfsEnumArray200 a200 = (netdfs.DfsEnumArray200)info.e;
+ SmbShareInfo[] entries = new SmbShareInfo[a200.count];
+ for (int i = 0; i < a200.count; i++) {
+ entries[i] = new SmbShareInfo(a200.s[i].dfs_name, 0, null);
+ }
+ return entries;
+ }
+}
--- /dev/null
+[
+ uuid(4fc742e0-4a10-11cf-8273-00aa004ae673),
+ version(3.0)
+]
+interface netdfs
+{
+ import "../rpc.idl";
+
+ const uint32_t DFS_VOLUME_FLAVOR_STANDALONE = 0x100;
+ const uint32_t DFS_VOLUME_FLAVOR_AD_BLOB = 0x200;
+
+ const uint32_t DFS_STORAGE_STATE_OFFLINE = 0x0001;
+ const uint32_t DFS_STORAGE_STATE_ONLINE = 0x0002;
+ const uint32_t DFS_STORAGE_STATE_ACTIVE = 0x0004;
+
+ typedef struct {
+ [string] wchar_t *entry_path;
+ } DfsInfo1;
+
+ typedef struct {
+ uint32_t count;
+ [size_is(count)] DfsInfo1 *s;
+ } DfsEnumArray1;
+
+ typedef struct {
+ uint32_t state;
+ [string] wchar_t *server_name;
+ [string] wchar_t *share_name;
+ } DfsStorageInfo;
+
+ typedef struct {
+ [string] wchar_t *path;
+ [string] wchar_t *comment;
+ uint32_t state;
+ uint32_t num_stores;
+ [size_is(num_stores)] DfsStorageInfo *stores;
+ } DfsInfo3;
+
+ typedef struct {
+ uint32_t count;
+ [size_is(count)] DfsInfo3 *s;
+ } DfsEnumArray3;
+
+ typedef struct {
+ [string] wchar_t *dfs_name;
+ } DfsInfo200;
+
+ typedef struct {
+ uint32_t count;
+ [size_is(count)] DfsInfo200 *s;
+ } DfsEnumArray200;
+
+ typedef struct {
+ uint32_t flags;
+ [string] wchar_t *dfs_name;
+ } DfsInfo300;
+
+ typedef struct {
+ uint32_t count;
+ [size_is(count)] DfsInfo300 *s;
+ } DfsEnumArray300;
+
+ typedef union {
+ [case(1)] DfsEnumArray1 *info1;
+ [case(3)] DfsEnumArray3 *info3;
+ [case(200)] DfsEnumArray200 *info200;
+ [case(300)] DfsEnumArray300 *info300;
+ } DfsEnumInfo;
+
+ typedef struct {
+ uint32_t level,
+ [switch_is(level)] DfsEnumInfo e;
+ } DfsEnumStruct;
+
+ [op(0x15)]
+ int NetrDfsEnumEx([in,string,unique] wchar_t dfs_name,
+ [in] uint32_t level,
+ [in] uint32_t prefmaxlen,
+ [in,out,unique] DfsEnumStruct *info,
+ [in,out,unique] uint32_t *totalentries);
+}
--- /dev/null
+package jcifs.dcerpc.msrpc;
+
+import jcifs.dcerpc.*;
+import jcifs.dcerpc.ndr.*;
+
+public class netdfs {
+
+ public static String getSyntax() {
+ return "4fc742e0-4a10-11cf-8273-00aa004ae673:3.0";
+ }
+
+ public static final int DFS_VOLUME_FLAVOR_STANDALONE = 0x100;
+ public static final int DFS_VOLUME_FLAVOR_AD_BLOB = 0x200;
+ public static final int DFS_STORAGE_STATE_OFFLINE = 0x0001;
+ public static final int DFS_STORAGE_STATE_ONLINE = 0x0002;
+ public static final int DFS_STORAGE_STATE_ACTIVE = 0x0004;
+ public static class DfsInfo1 extends NdrObject {
+
+ public String entry_path;
+
+ public void encode(NdrBuffer _dst) throws NdrException {
+ _dst.align(4);
+ _dst.enc_ndr_referent(entry_path, 1);
+
+ if (entry_path != null) {
+ _dst = _dst.deferred;
+ _dst.enc_ndr_string(entry_path);
+
+ }
+ }
+ public void decode(NdrBuffer _src) throws NdrException {
+ _src.align(4);
+ int _entry_pathp = _src.dec_ndr_long();
+
+ if (_entry_pathp != 0) {
+ _src = _src.deferred;
+ entry_path = _src.dec_ndr_string();
+
+ }
+ }
+ }
+ public static class DfsEnumArray1 extends NdrObject {
+
+ public int count;
+ public DfsInfo1[] s;
+
+ public void encode(NdrBuffer _dst) throws NdrException {
+ _dst.align(4);
+ _dst.enc_ndr_long(count);
+ _dst.enc_ndr_referent(s, 1);
+
+ if (s != null) {
+ _dst = _dst.deferred;
+ int _ss = count;
+ _dst.enc_ndr_long(_ss);
+ int _si = _dst.index;
+ _dst.advance(4 * _ss);
+
+ _dst = _dst.derive(_si);
+ for (int _i = 0; _i < _ss; _i++) {
+ s[_i].encode(_dst);
+ }
+ }
+ }
+ public void decode(NdrBuffer _src) throws NdrException {
+ _src.align(4);
+ count = (int)_src.dec_ndr_long();
+ int _sp = _src.dec_ndr_long();
+
+ if (_sp != 0) {
+ _src = _src.deferred;
+ int _ss = _src.dec_ndr_long();
+ int _si = _src.index;
+ _src.advance(4 * _ss);
+
+ if (s == null) {
+ if (_ss < 0 || _ss > 0xFFFF) throw new NdrException( NdrException.INVALID_CONFORMANCE );
+ s = new DfsInfo1[_ss];
+ }
+ _src = _src.derive(_si);
+ for (int _i = 0; _i < _ss; _i++) {
+ if (s[_i] == null) {
+ s[_i] = new DfsInfo1();
+ }
+ s[_i].decode(_src);
+ }
+ }
+ }
+ }
+ public static class DfsStorageInfo extends NdrObject {
+
+ public int state;
+ public String server_name;
+ public String share_name;
+
+ public void encode(NdrBuffer _dst) throws NdrException {
+ _dst.align(4);
+ _dst.enc_ndr_long(state);
+ _dst.enc_ndr_referent(server_name, 1);
+ _dst.enc_ndr_referent(share_name, 1);
+
+ if (server_name != null) {
+ _dst = _dst.deferred;
+ _dst.enc_ndr_string(server_name);
+
+ }
+ if (share_name != null) {
+ _dst = _dst.deferred;
+ _dst.enc_ndr_string(share_name);
+
+ }
+ }
+ public void decode(NdrBuffer _src) throws NdrException {
+ _src.align(4);
+ state = (int)_src.dec_ndr_long();
+ int _server_namep = _src.dec_ndr_long();
+ int _share_namep = _src.dec_ndr_long();
+
+ if (_server_namep != 0) {
+ _src = _src.deferred;
+ server_name = _src.dec_ndr_string();
+
+ }
+ if (_share_namep != 0) {
+ _src = _src.deferred;
+ share_name = _src.dec_ndr_string();
+
+ }
+ }
+ }
+ public static class DfsInfo3 extends NdrObject {
+
+ public String path;
+ public String comment;
+ public int state;
+ public int num_stores;
+ public DfsStorageInfo[] stores;
+
+ public void encode(NdrBuffer _dst) throws NdrException {
+ _dst.align(4);
+ _dst.enc_ndr_referent(path, 1);
+ _dst.enc_ndr_referent(comment, 1);
+ _dst.enc_ndr_long(state);
+ _dst.enc_ndr_long(num_stores);
+ _dst.enc_ndr_referent(stores, 1);
+
+ if (path != null) {
+ _dst = _dst.deferred;
+ _dst.enc_ndr_string(path);
+
+ }
+ if (comment != null) {
+ _dst = _dst.deferred;
+ _dst.enc_ndr_string(comment);
+
+ }
+ if (stores != null) {
+ _dst = _dst.deferred;
+ int _storess = num_stores;
+ _dst.enc_ndr_long(_storess);
+ int _storesi = _dst.index;
+ _dst.advance(12 * _storess);
+
+ _dst = _dst.derive(_storesi);
+ for (int _i = 0; _i < _storess; _i++) {
+ stores[_i].encode(_dst);
+ }
+ }
+ }
+ public void decode(NdrBuffer _src) throws NdrException {
+ _src.align(4);
+ int _pathp = _src.dec_ndr_long();
+ int _commentp = _src.dec_ndr_long();
+ state = (int)_src.dec_ndr_long();
+ num_stores = (int)_src.dec_ndr_long();
+ int _storesp = _src.dec_ndr_long();
+
+ if (_pathp != 0) {
+ _src = _src.deferred;
+ path = _src.dec_ndr_string();
+
+ }
+ if (_commentp != 0) {
+ _src = _src.deferred;
+ comment = _src.dec_ndr_string();
+
+ }
+ if (_storesp != 0) {
+ _src = _src.deferred;
+ int _storess = _src.dec_ndr_long();
+ int _storesi = _src.index;
+ _src.advance(12 * _storess);
+
+ if (stores == null) {
+ if (_storess < 0 || _storess > 0xFFFF) throw new NdrException( NdrException.INVALID_CONFORMANCE );
+ stores = new DfsStorageInfo[_storess];
+ }
+ _src = _src.derive(_storesi);
+ for (int _i = 0; _i < _storess; _i++) {
+ if (stores[_i] == null) {
+ stores[_i] = new DfsStorageInfo();
+ }
+ stores[_i].decode(_src);
+ }
+ }
+ }
+ }
+ public static class DfsEnumArray3 extends NdrObject {
+
+ public int count;
+ public DfsInfo3[] s;
+
+ public void encode(NdrBuffer _dst) throws NdrException {
+ _dst.align(4);
+ _dst.enc_ndr_long(count);
+ _dst.enc_ndr_referent(s, 1);
+
+ if (s != null) {
+ _dst = _dst.deferred;
+ int _ss = count;
+ _dst.enc_ndr_long(_ss);
+ int _si = _dst.index;
+ _dst.advance(20 * _ss);
+
+ _dst = _dst.derive(_si);
+ for (int _i = 0; _i < _ss; _i++) {
+ s[_i].encode(_dst);
+ }
+ }
+ }
+ public void decode(NdrBuffer _src) throws NdrException {
+ _src.align(4);
+ count = (int)_src.dec_ndr_long();
+ int _sp = _src.dec_ndr_long();
+
+ if (_sp != 0) {
+ _src = _src.deferred;
+ int _ss = _src.dec_ndr_long();
+ int _si = _src.index;
+ _src.advance(20 * _ss);
+
+ if (s == null) {
+ if (_ss < 0 || _ss > 0xFFFF) throw new NdrException( NdrException.INVALID_CONFORMANCE );
+ s = new DfsInfo3[_ss];
+ }
+ _src = _src.derive(_si);
+ for (int _i = 0; _i < _ss; _i++) {
+ if (s[_i] == null) {
+ s[_i] = new DfsInfo3();
+ }
+ s[_i].decode(_src);
+ }
+ }
+ }
+ }
+ public static class DfsInfo200 extends NdrObject {
+
+ public String dfs_name;
+
+ public void encode(NdrBuffer _dst) throws NdrException {
+ _dst.align(4);
+ _dst.enc_ndr_referent(dfs_name, 1);
+
+ if (dfs_name != null) {
+ _dst = _dst.deferred;
+ _dst.enc_ndr_string(dfs_name);
+
+ }
+ }
+ public void decode(NdrBuffer _src) throws NdrException {
+ _src.align(4);
+ int _dfs_namep = _src.dec_ndr_long();
+
+ if (_dfs_namep != 0) {
+ _src = _src.deferred;
+ dfs_name = _src.dec_ndr_string();
+
+ }
+ }
+ }
+ public static class DfsEnumArray200 extends NdrObject {
+
+ public int count;
+ public DfsInfo200[] s;
+
+ public void encode(NdrBuffer _dst) throws NdrException {
+ _dst.align(4);
+ _dst.enc_ndr_long(count);
+ _dst.enc_ndr_referent(s, 1);
+
+ if (s != null) {
+ _dst = _dst.deferred;
+ int _ss = count;
+ _dst.enc_ndr_long(_ss);
+ int _si = _dst.index;
+ _dst.advance(4 * _ss);
+
+ _dst = _dst.derive(_si);
+ for (int _i = 0; _i < _ss; _i++) {
+ s[_i].encode(_dst);
+ }
+ }
+ }
+ public void decode(NdrBuffer _src) throws NdrException {
+ _src.align(4);
+ count = (int)_src.dec_ndr_long();
+ int _sp = _src.dec_ndr_long();
+
+ if (_sp != 0) {
+ _src = _src.deferred;
+ int _ss = _src.dec_ndr_long();
+ int _si = _src.index;
+ _src.advance(4 * _ss);
+
+ if (s == null) {
+ if (_ss < 0 || _ss > 0xFFFF) throw new NdrException( NdrException.INVALID_CONFORMANCE );
+ s = new DfsInfo200[_ss];
+ }
+ _src = _src.derive(_si);
+ for (int _i = 0; _i < _ss; _i++) {
+ if (s[_i] == null) {
+ s[_i] = new DfsInfo200();
+ }
+ s[_i].decode(_src);
+ }
+ }
+ }
+ }
+ public static class DfsInfo300 extends NdrObject {
+
+ public int flags;
+ public String dfs_name;
+
+ public void encode(NdrBuffer _dst) throws NdrException {
+ _dst.align(4);
+ _dst.enc_ndr_long(flags);
+ _dst.enc_ndr_referent(dfs_name, 1);
+
+ if (dfs_name != null) {
+ _dst = _dst.deferred;
+ _dst.enc_ndr_string(dfs_name);
+
+ }
+ }
+ public void decode(NdrBuffer _src) throws NdrException {
+ _src.align(4);
+ flags = (int)_src.dec_ndr_long();
+ int _dfs_namep = _src.dec_ndr_long();
+
+ if (_dfs_namep != 0) {
+ _src = _src.deferred;
+ dfs_name = _src.dec_ndr_string();
+
+ }
+ }
+ }
+ public static class DfsEnumArray300 extends NdrObject {
+
+ public int count;
+ public DfsInfo300[] s;
+
+ public void encode(NdrBuffer _dst) throws NdrException {
+ _dst.align(4);
+ _dst.enc_ndr_long(count);
+ _dst.enc_ndr_referent(s, 1);
+
+ if (s != null) {
+ _dst = _dst.deferred;
+ int _ss = count;
+ _dst.enc_ndr_long(_ss);
+ int _si = _dst.index;
+ _dst.advance(8 * _ss);
+
+ _dst = _dst.derive(_si);
+ for (int _i = 0; _i < _ss; _i++) {
+ s[_i].encode(_dst);
+ }
+ }
+ }
+ public void decode(NdrBuffer _src) throws NdrException {
+ _src.align(4);
+ count = (int)_src.dec_ndr_long();
+ int _sp = _src.dec_ndr_long();
+
+ if (_sp != 0) {
+ _src = _src.deferred;
+ int _ss = _src.dec_ndr_long();
+ int _si = _src.index;
+ _src.advance(8 * _ss);
+
+ if (s == null) {
+ if (_ss < 0 || _ss > 0xFFFF) throw new NdrException( NdrException.INVALID_CONFORMANCE );
+ s = new DfsInfo300[_ss];
+ }
+ _src = _src.derive(_si);
+ for (int _i = 0; _i < _ss; _i++) {
+ if (s[_i] == null) {
+ s[_i] = new DfsInfo300();
+ }
+ s[_i].decode(_src);
+ }
+ }
+ }
+ }
+ public static class DfsEnumStruct extends NdrObject {
+
+ public int level;
+ public NdrObject e;
+
+ public void encode(NdrBuffer _dst) throws NdrException {
+ _dst.align(4);
+ _dst.enc_ndr_long(level);
+ int _descr = level;
+ _dst.enc_ndr_long(_descr);
+ _dst.enc_ndr_referent(e, 1);
+
+ if (e != null) {
+ _dst = _dst.deferred;
+ e.encode(_dst);
+
+ }
+ }
+ public void decode(NdrBuffer _src) throws NdrException {
+ _src.align(4);
+ level = (int)_src.dec_ndr_long();
+ _src.dec_ndr_long(); /* union discriminant */
+ int _ep = _src.dec_ndr_long();
+
+ if (_ep != 0) {
+ if (e == null) { /* YOYOYO */
+ e = new DfsEnumArray1();
+ }
+ _src = _src.deferred;
+ e.decode(_src);
+
+ }
+ }
+ }
+ public static class NetrDfsEnumEx extends DcerpcMessage {
+
+ public int getOpnum() { return 0x15; }
+
+ public int retval;
+ public String dfs_name;
+ public int level;
+ public int prefmaxlen;
+ public DfsEnumStruct info;
+ public NdrLong totalentries;
+
+ public NetrDfsEnumEx(String dfs_name,
+ int level,
+ int prefmaxlen,
+ DfsEnumStruct info,
+ NdrLong totalentries) {
+ this.dfs_name = dfs_name;
+ this.level = level;
+ this.prefmaxlen = prefmaxlen;
+ this.info = info;
+ this.totalentries = totalentries;
+ }
+
+ public void encode_in(NdrBuffer _dst) throws NdrException {
+ _dst.enc_ndr_string(dfs_name);
+ _dst.enc_ndr_long(level);
+ _dst.enc_ndr_long(prefmaxlen);
+ _dst.enc_ndr_referent(info, 1);
+ if (info != null) {
+ info.encode(_dst);
+
+ }
+ _dst.enc_ndr_referent(totalentries, 1);
+ if (totalentries != null) {
+ totalentries.encode(_dst);
+
+ }
+ }
+ public void decode_out(NdrBuffer _src) throws NdrException {
+ int _infop = _src.dec_ndr_long();
+ if (_infop != 0) {
+ if (info == null) { /* YOYOYO */
+ info = new DfsEnumStruct();
+ }
+ info.decode(_src);
+
+ }
+ int _totalentriesp = _src.dec_ndr_long();
+ if (_totalentriesp != 0) {
+ totalentries.decode(_src);
+
+ }
+ retval = (int)_src.dec_ndr_long();
+ }
+ }
+}
StringBuffer redir = req.getRequestURL();
String qs = req.getQueryString();
redir = new StringBuffer( redir.substring( 0, redir.length() - req.getPathInfo().length() ));
- redir.append( dr.node.replace( '\\', '/' ));
+ redir.append( '/' );
+ redir.append(dr.server);
+ redir.append( '/' );
+ redir.append(dr.share);
redir.append( '/' );
if( qs != null ) {
redir.append( req.getQueryString() );
--- /dev/null
+/* jcifs smb client library in Java
+ * Copyright (C) 2008 "Michael B. Allen" <jcifs at samba dot org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package jcifs.smb;
+
+import java.util.*;
+import java.io.*;
+
+import jcifs.UniAddress;
+import jcifs.util.*;
+import jcifs.Config;
+
+public class Dfs {
+
+ static class CacheEntry {
+ long expiration;
+ HashMap map;
+
+ CacheEntry(long ttl) {
+ if (ttl == 0)
+ ttl = Dfs.TTL;
+ expiration = System.currentTimeMillis() + ttl * 1000L;
+ map = new HashMap();
+ }
+ }
+
+ 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);
+
+ protected static CacheEntry FALSE_ENTRY = new Dfs.CacheEntry(0L);
+
+ protected CacheEntry _domains = null; /* aka trusted domains cache */
+ protected CacheEntry referrals = null;
+
+ public HashMap getTrustedDomains(NtlmPasswordAuthentication auth) throws SmbAuthException {
+ if (_domains != null && System.currentTimeMillis() > _domains.expiration) {
+ _domains = null;
+ }
+ if (_domains != null)
+ return _domains.map;
+ try {
+ UniAddress addr = UniAddress.getByName(auth.domain);
+ SmbTransport trans = SmbTransport.getSmbTransport(addr, 0);
+ DfsReferral[] dr = trans.getDfsReferrals(auth, "", 0);
+ CacheEntry entry = new CacheEntry(Dfs.TTL * 10L);
+ for (int di = 0; di < dr.length; di++) {
+ String domain = dr[di].server;
+ entry.map.put(domain, new HashMap());
+ }
+ _domains = entry;
+ return _domains.map;
+ } catch (IOException ioe) {
+ if (log.level >= 3)
+ ioe.printStackTrace(log);
+ if (strictView && ioe instanceof SmbAuthException) {
+ throw (SmbAuthException)ioe;
+ }
+ }
+ return null;
+ }
+ public boolean isTrustedDomain(String domain,
+ NtlmPasswordAuthentication auth) throws SmbAuthException
+ {
+ HashMap domains = getTrustedDomains(auth);
+ if (domains == null)
+ return false;
+ domain = domain.toLowerCase();
+ return domains.get(domain) != null;
+ }
+ public SmbTransport getDc(String domain,
+ NtlmPasswordAuthentication auth) throws SmbAuthException {
+ try {
+ UniAddress addr = UniAddress.getByName(domain);
+ SmbTransport trans = SmbTransport.getSmbTransport(addr, 0);
+ DfsReferral[] dr = trans.getDfsReferrals(auth, "\\" + domain, 1);
+ if (dr.length == 1) {
+ addr = UniAddress.getByName(dr[0].server);
+ return SmbTransport.getSmbTransport(addr, 0);
+ }
+ } catch (IOException ioe) {
+ if (log.level >= 3)
+ ioe.printStackTrace(log);
+ if (strictView && ioe instanceof SmbAuthException) {
+ throw (SmbAuthException)ioe;
+ }
+ }
+ return null;
+ }
+ public DfsReferral getReferral(SmbTransport trans,
+ String domain,
+ String root,
+ String path,
+ NtlmPasswordAuthentication auth) throws SmbAuthException {
+ try {
+ String p = "\\" + domain + "\\" + root;
+ if (path != null)
+ p += path;
+ DfsReferral[] dr = trans.getDfsReferrals(auth, p, 1);
+ if (dr.length == 1)
+ return dr[0];
+ } catch (IOException ioe) {
+ if (log.level >= 3)
+ ioe.printStackTrace(log);
+ if (strictView && ioe instanceof SmbAuthException) {
+ throw (SmbAuthException)ioe;
+ }
+ }
+ return null;
+ }
+ public DfsReferral resolve(String domain,
+ String root,
+ String path,
+ NtlmPasswordAuthentication auth) throws SmbAuthException {
+ DfsReferral dr = null;
+ long now = System.currentTimeMillis();
+
+ if (root.equals("IPC$")) {
+ return null;
+ }
+ HashMap domains = getTrustedDomains(auth);
+ if (domains != null) {
+ domain = domain.toLowerCase();
+ HashMap roots = (HashMap)domains.get(domain);
+ if (roots != null) {
+ SmbTransport trans = null;
+
+ root = root.toLowerCase();
+
+ CacheEntry links = (CacheEntry)roots.get(root);
+ if (links != null && now > links.expiration) {
+ roots.remove(root);
+ links = null;
+ }
+ if (links == null) {
+ if ((trans = getDc(domain, auth)) == null)
+ return null;
+
+ dr = getReferral(trans, domain, root, path, auth);
+ if (dr != null) {
+ dr.pathConsumed -= 1 + domain.length() + 1 + root.length();
+ links = new CacheEntry(0L);
+ if (path == null)
+ links.map.put("\\", dr);
+ roots.put(root, links);
+ } else if (path == null) {
+ roots.put(root, Dfs.FALSE_ENTRY);
+ }
+ } else if (links == Dfs.FALSE_ENTRY) {
+ links = null;
+ }
+
+ if (links != null) {
+ String link = "\\";
+ if (path != null) {
+ int i = path.indexOf("\\", 1);
+ link = i > 0 ? path.substring(1, i) : path.substring(1);
+ }
+
+ dr = (DfsReferral)links.map.get(link);
+ if (dr != null && now > dr.expiration) {
+ dr = null;
+ links.map.remove(link);
+ }
+ if (dr == null) {
+ if (trans == null)
+ if ((trans = getDc(domain, auth)) == null)
+ return null;
+ dr = getReferral(trans, domain, root, path, auth);
+ if (dr != null) {
+ dr.pathConsumed -= 1 + domain.length() + 1 + root.length();
+ dr.link = link;
+ links.map.put(link, dr);
+ }
+ }
+ }
+ }
+ }
+
+ if (dr == null && path != null) {
+ /* The referrals map is for stand-alone roots
+ */
+ if (referrals != null && now > referrals.expiration) {
+ referrals = null;
+ }
+ if (referrals == null) {
+ referrals = new CacheEntry(0);
+ }
+ String key = "\\" + domain + "\\" + root;
+ if (path.equals("\\") == false) {
+ int s1 = path.indexOf('\\', 1);
+ if (s1 > 0)
+ path = path.substring(0, s1);
+ key += path;
+ }
+ dr = (DfsReferral)referrals.map.get(key.toLowerCase());
+ }
+
+ return dr;
+ }
+ void insert(String path, DfsReferral dr) {
+ int s1, s2;
+ String server, share, key;
+
+ s1 = path.indexOf('\\', 1);
+ s2 = path.indexOf('\\', s1 + 1);
+ server = path.substring(1, s1);
+ share = path.substring(s1 + 1, s2);
+
+ key = path.substring(0, dr.pathConsumed).toLowerCase();
+ dr.pathConsumed -= 1 + server.length() + 1 + share.length();
+
+ if (referrals != null && (System.currentTimeMillis() + 10000) > referrals.expiration) {
+ referrals = null;
+ }
+ if (referrals == null) {
+ referrals = new CacheEntry(0);
+ }
+ referrals.map.put(key, dr);
+ }
+}
public class DfsReferral extends SmbException {
- public String path; // Path relative to tree from which this referral was thrown
- public String node; // Server and share
+ public int pathConsumed;
+ public long ttl;
public String server; // Server
public String share; // Share
- public String nodepath; // Path relative to tree
+ public String link;
+ public String path; // Path relative to tree from which this referral was thrown
public boolean resolveHashes;
+ public long expiration;
public String toString() {
- return "DfsReferral[path=" + path +
- ",node=" + node +
+ return "DfsReferral[pathConsumed=" + pathConsumed +
",server=" + server +
",share=" + share +
- ",nodepath=" + nodepath +
+ ",link=" + link +
+ ",path=" + path +
+ ",ttl=" + ttl +
+ ",expiration=" + expiration +
",resolveHashes=" + resolveHashes + "]";
}
}
{ 0x00030002, 0xc00000cb },
{ 0x00040002, 0xc00000ca },
{ 0x00050001, 0xc0000022 },
- { 0x00050002, 0xc00000c9 },
+ { 0x00050002, 0xc000000d },
{ 0x00060001, 0xc0000008 },
{ 0x00060002, 0xc00000cc },
{ 0x00080001, 0xc000009a },
{ 0x00500001, 0xc0000035 },
{ 0x00570001, 0xc0000003 },
{ 0x005a0002, 0xc00000ce },
+ { 0x005b0002, 0xc000000d },
{ 0x006d0001, 0xC000014b },
{ 0x007b0001, 0xc0000033 },
{ 0x00910001, 0xC0000101 },
"The file exists.",
"The parameter is incorrect.",
"Too many Uids active on this session.",
+ "The Uid is not known as a valid user identifier on this session.",
"The pipe has been ended.",
"The filename, directory name, or volume label syntax is incorrect.",
"The directory is not empty.",
return 0;
}
public String toString() {
- return new String( "NtTransGetSecurityDesc[" + super.toString() +
+ return new String( "NtTransQuerySecurityDesc[" + super.toString() +
",fid=0x" + Hexdump.toHexString( fid, 4 ) +
",securityInformation=0x" + Hexdump.toHexString( securityInformation, 8 ) + "]" );
}
public String getDomain() {
return domain;
}
+
/**
* Returns the username.
*/
public class SmbException extends IOException implements NtStatus, DosError, WinError {
static String getMessageByCode( int errcode ) {
+ /* Note there's a signedness error here because 0xC0000000 based values are
+ * negative so it with NT_STATUS_SUCCESS (0) the binary search will not be
+ * performed properly. The effect is that the code at index 1 is never found
+ * (NT_STATUS_UNSUCCESSFUL). So here we factor out NT_STATUS_SUCCESS
+ * as a special case (which it is).
+ */
+ if (errcode == 0) {
+ return "NT_STATUS_SUCCESS";
+ }
if(( errcode & 0xC0000000 ) == 0xC0000000 ) {
- int min = 0;
+ int min = 1; /* Don't include NT_STATUS_SUCCESS */
int max = NT_STATUS_CODES.length - 1;
while( max >= min ) {
int mid = (min + max) / 2;
- /* Note there's a signedness error here because 0xC0000000 based values are
- * negative so it with NT_STATUS_SUCCESS (0) the binary search will not be
- * performed properly. The effect is that the code at index 1 is never found
- * (NT_STATUS_UNSUCCESSFUL). We should just factor out NT_STATUS_SUCCESS
- * as a special case (which it is).
- */
if( errcode > NT_STATUS_CODES[mid] ) {
min = mid + 1;
} else if( errcode < NT_STATUS_CODES[mid] ) {
cnfe.printStackTrace();
}
attrExpirationPeriod = Config.getLong( "jcifs.smb.client.attrExpirationPeriod", DEFAULT_ATTR_EXPIRATION_PERIOD );
+ dfs = new Dfs();
}
/**
private boolean isExists;
private int shareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
private SmbComBlankResponse blank_resp = null;
- private DfsReferral dfsReferral = null; // Only used by getDfsPath()
+ private DfsReferral dfsReferral = null; // For getDfsPath() and getServerWithDfs()
+
+ protected static Dfs dfs;
NtlmPasswordAuthentication auth; // Cannot be null
SmbTree tree = null; // Initially null; may be !tree.treeConnected
}
return blank_resp;
}
- void send( ServerMessageBlock request,
- ServerMessageBlock response ) throws SmbException {
- for( ;; ) {
- connect0();
- if( tree.inDfs ) {
- DfsReferral dr = tree.session.transport.lookupReferral( unc );
- if( dr != null ) {
- UniAddress addr;
- SmbTransport trans;
-
- try {
- addr = UniAddress.getByName( dr.server );
- } catch( UnknownHostException uhe ) {
- throw new SmbException( dr.server, uhe );
- }
+ void resolveDfs(ServerMessageBlock request) throws SmbException {
+ connect0();
+ String hostName = getServerWithDfs();
+ DfsReferral dr = dfs.resolve(
+ hostName,
+ tree.share,
+ unc,
+ auth);
+ if (dr != null) {
+ UniAddress addr;
+ SmbTransport trans;
- trans = SmbTransport.getSmbTransport( addr, url.getPort() );
- tree = trans.getSmbSession( auth ).getSmbTree( dr.share, null );
+ try {
+ addr = UniAddress.getByName( dr.server );
+ } catch( UnknownHostException uhe ) {
+ throw new SmbException( dr.server, uhe );
+ }
- if (log.level >= 3)
- log.println( dr );
-
- dfsReferral = dr;
- String dunc = dfsReferral.nodepath + unc.substring( dfsReferral.path.length() );
- unc = dunc;
- if (request.path.endsWith("\\") && dunc.endsWith("\\") == false)
- dunc += "\\";
- request.path = dunc;
- }
+ trans = SmbTransport.getSmbTransport( addr, url.getPort() );
+ tree = trans.getSmbSession( auth ).getSmbTree( dr.share, null );
+
+ if (log.level >= 3)
+ log.println( dr );
+
+ dfsReferral = dr;
+ String dunc = unc.substring(dr.pathConsumed);
+ if (dunc.equals(""))
+ dunc = "\\";
+ unc = dunc;
+ if (request != null &&
+ request.path != null &&
+ request.path.endsWith("\\") &&
+ dunc.endsWith("\\") == false) {
+ dunc += "\\";
+ }
+ if (request != null) {
+ request.path = dunc;
request.flags2 |= ServerMessageBlock.FLAGS2_RESOLVE_PATHS_IN_DFS;
- } else {
- request.flags2 &= ~ServerMessageBlock.FLAGS2_RESOLVE_PATHS_IN_DFS;
}
+ } else if (tree.inDomainDfs &&
+ !(request instanceof NtTransQuerySecurityDesc) &&
+ !(request instanceof SmbComClose) &&
+ !(request instanceof SmbComFindClose2)) {
+ throw new SmbException(NtStatus.NT_STATUS_NOT_FOUND, false);
+ } else {
+ if (request != null)
+ request.flags2 &= ~ServerMessageBlock.FLAGS2_RESOLVE_PATHS_IN_DFS;
+ }
+ }
+ void send( ServerMessageBlock request,
+ ServerMessageBlock response ) throws SmbException {
+ for( ;; ) {
+ resolveDfs(request);
try {
tree.send( request, response );
break;
- } catch( DfsReferral dr ) {
- if( dr.resolveHashes ) {
- throw dr;
+ } catch( DfsReferral dre ) {
+ if( dre.resolveHashes ) {
+ throw dre;
}
request.reset();
}
}
void doConnect() throws IOException {
SmbTransport trans;
- SmbSession ssn;
UniAddress addr;
addr = getAddress();
- trans = SmbTransport.getSmbTransport(addr, url.getPort());
- ssn = trans.getSmbSession(auth);
- tree = ssn.getSmbTree(share, null);
+ if (tree != null) {
+ trans = tree.session.transport;
+ } else {
+ trans = SmbTransport.getSmbTransport(addr, url.getPort());
+ tree = trans.getSmbSession(auth).getSmbTree(share, null);
+ }
+
+ String hostName = getServerWithDfs();
+ tree.inDomainDfs = dfs.resolve(hostName, tree.share, null, auth) != null;
+ if (tree.inDomainDfs) {
+ tree.treeConnected = true;
+ }
try {
if( log.level >= 3 )
tree.treeConnect(null, null);
} catch (SmbAuthException sae) {
NtlmPasswordAuthentication a;
+ SmbSession ssn;
if (share == null) { // IPC$ - try "anonymous" credentials
ssn = trans.getSmbSession(NtlmPasswordAuthentication.NULL);
auth = a;
ssn = trans.getSmbSession(auth);
tree = ssn.getSmbTree(share, null);
+ tree.inDomainDfs = dfs.resolve(hostName, tree.share, null, auth) != null;
+ if (tree.inDomainDfs) {
+ tree.treeConnected = true;
+ }
tree.treeConnect(null, null);
} else {
if (log.level >= 1 && hasNextAddress())
isExists = true;
} else {
SmbComOpenAndXResponse response = new SmbComOpenAndXResponse();
- send( new SmbComOpenAndX( unc, flags, access, null ), response );
+ send( new SmbComOpenAndX( unc, access, flags, null ), response );
f = response.fid;
}
String getServerWithDfs() {
if (dfsReferral != null) {
- /* Don't use dfsReferral.server because vers 1 referrals don't have it
- */
- char[] server = dfsReferral.node.toCharArray();
- int start, end;
-
- start = 0;
- while (start < server.length && server[start] == '\\') {
- start++;
- }
- end = start;
- while (end < server.length && server[end] != '\\') {
- end++;
- }
-
- return new String(server, start, end - start);
+ return dfsReferral.server;
}
-
return getServer();
}
/**
*/
public String getDfsPath() throws SmbException {
- connect0();
- if( tree.inDfs ) {
- exists();
- }
+ resolveDfs(null);
if( dfsReferral == null ) {
return null;
}
- String path = "smb:/" + dfsReferral.node + unc;
+ String path = "smb:/" + dfsReferral.server + "/" + dfsReferral.share + unc;
path = path.replace( '\\', '/' );
if (isDirectory()) {
path += '/';
map = new HashMap();
+ if (dfs.isTrustedDomain(getServer(), auth)) {
+ /* The server name is actually the name of a trusted
+ * domain. Add DFS roots to the list.
+ */
+ try {
+ entries = doDfsRootEnum();
+ for (int ei = 0; ei < entries.length; ei++) {
+ e = entries[ei];
+ if (map.containsKey(e) == false)
+ map.put(e, e);
+ }
+ } catch (IOException ioe) {
+ if (log.level >= 4)
+ ioe.printStackTrace(log);
+ }
+ }
+
addr = getFirstAddress();
while (addr != null) {
try {
if (map.containsKey(e) == false)
map.put(e, e);
}
+ break;
} catch(IOException ioe) {
if (log.level >= 3)
ioe.printStackTrace(log);
}
}
}
+ FileEntry[] doDfsRootEnum() throws IOException {
+ MsrpcDfsRootEnum rpc;
+ DcerpcHandle handle = null;
+ FileEntry[] entries;
+
+ handle = DcerpcHandle.getHandle("ncacn_np:" +
+ getAddress().getHostAddress() +
+ "[\\PIPE\\netdfs]", auth);
+ try {
+ rpc = new MsrpcDfsRootEnum(getServer());
+ handle.sendrecv(rpc);
+ if (rpc.retval != 0)
+ throw new SmbException(rpc.retval, true);
+ return rpc.getEntries();
+ } finally {
+ try {
+ handle.close();
+ } catch(IOException ioe) {
+ if (log.level >= 4)
+ ioe.printStackTrace(log);
+ }
+ }
+ }
FileEntry[] doMsrpcShareEnum() throws IOException {
MsrpcShareEnum rpc;
DcerpcHandle handle;
resp.reset();
} while(more);
}
- void doNetEnumX( ArrayList list,
- boolean files,
- String wildcard,
- int searchAttributes,
- SmbFilenameFilter fnf,
- SmbFileFilter ff ) throws SmbException,
- UnknownHostException, MalformedURLException {
- SmbComTransaction req;
- SmbComTransactionResponse resp;
- int listType = url.getHost().length() == 0 ? 0 : getType();
- String p = url.getPath();
-
- if( p.lastIndexOf( '/' ) != ( p.length() - 1 )) {
- throw new SmbException( url.toString() + " directory must end with '/'" );
- }
-
- switch( listType ) {
- case 0:
- connect0();
- req = new NetServerEnum2( tree.session.transport.server.oemDomainName,
- NetServerEnum2.SV_TYPE_DOMAIN_ENUM );
- resp = new NetServerEnum2Response();
- break;
- case TYPE_WORKGROUP:
- req = new NetServerEnum2( url.getHost(), NetServerEnum2.SV_TYPE_ALL );
- resp = new NetServerEnum2Response();
- break;
- case TYPE_SERVER:
- req = new NetShareEnum();
- resp = new NetShareEnumResponse();
- break;
- default:
- throw new SmbException( "The requested list operations is invalid: " + url.toString() );
- }
-
- boolean more;
- do {
- int n;
-
- send( req, resp );
-
- more = resp.status == SmbException.ERROR_MORE_DATA;
-
- if( resp.status != SmbException.ERROR_SUCCESS &&
- resp.status != SmbException.ERROR_MORE_DATA ) {
- throw new SmbException( resp.status, true );
- }
-
- n = more ? resp.numEntries - 1 : resp.numEntries;
- for( int i = 0; i < n; i++ ) {
- FileEntry e = resp.results[i];
- String name = e.getName();
- if( fnf != null && fnf.accept( this, name ) == false ) {
- continue;
- }
- if( name.length() > 0 ) {
- SmbFile f = new SmbFile( this, name,
- e.getType(),
- ATTR_READONLY | ATTR_DIRECTORY, 0L, 0L, 0L );
- if( ff != null && ff.accept( f ) == false ) {
- continue;
- }
- if( files ) {
- list.add( f );
- } else {
- list.add( name );
- }
- }
- }
- if( listType != 0 && listType != TYPE_WORKGROUP ) {
- break;
- }
- req.subCommand = (byte)SmbComTransaction.NET_SERVER_ENUM3;
- req.reset( 0, ((NetServerEnum2Response)resp).lastName );
- resp.reset();
- } while( more );
- }
void doFindFirstNext( ArrayList list,
boolean files,
String wildcard,
if( getUncPath0().length() == 1 || dest.getUncPath0().length() == 1 ) {
throw new SmbException( "Invalid operation for workgroups, servers, or shares" );
}
- connect0();
- dest.connect0();
- if( tree.inDfs ) { /* This ensures that each path is
- * resolved independantly to deal with the case where files
- * have the same base path but ultimately turn out to be
- * on different servers because of DFS. It also eliminates
- * manipulating the SMB path which is problematic because
- * there are really two that would need to be prefixed
- * with host and share as DFS requires.
- */
- exists();
- dest.exists();
- }
+ resolveDfs(null);
+ dest.resolveDfs(null);
+
if (!tree.equals(dest.tree)) {
throw new SmbException( "Invalid operation for workgroups, servers, or shares" );
}
connect0();
dest.connect0();
- if( tree.inDfs ) {
/* At this point the maxBufferSize values are from the server
* exporting the volumes, not the one that we will actually
* end up performing IO with. If the server hosting the
* establishing buffer size. These exists() calls facilitate
* that.
*/
- exists();
- dest.exists();
- }
+ resolveDfs(null);
/* It is invalid for the source path to be a child of the destination
* path or visa versa.
* @throws SmbException
*/
public void delete() throws SmbException {
- if( tree == null || tree.inDfs ) {
- exists(); /* This is necessary to ensure we
- * pass a path adjusted for DFS */
- }
+ exists();
getUncPath0();
delete( unc );
}
return hash + canon.toUpperCase().hashCode();
}
+ protected boolean pathNamesPossiblyEqual(String path1, String path2) {
+ int p1, p2, l1, l2;
+
+ // if unsure return this method returns true
+
+ p1 = path1.lastIndexOf('/');
+ p2 = path2.lastIndexOf('/');
+ l1 = path1.length() - p1;
+ l2 = path2.length() - p2;
+
+ // anything with dots voids comparison
+ if (l1 > 1 && path1.charAt(p1 + 1) == '.')
+ return true;
+ if (l2 > 1 && path2.charAt(p2 + 1) == '.')
+ return true;
+
+ return l1 == l2 && path1.regionMatches(true, p1, path2, p2, l1);
+ }
/**
* Tests to see if two <code>SmbFile</code> objects are equal. Two
* SmbFile objects are equal when they reference the same SMB
*/
public boolean equals( Object obj ) {
+ if (obj instanceof SmbFile) {
+ SmbFile f = (SmbFile)obj;
+ boolean ret;
+
+ if (this == f)
+ return true;
+
+ /* If uncertain, pathNamesPossiblyEqual returns true.
+ * Comparing canonical paths is definitive.
+ */
+ if (pathNamesPossiblyEqual(url.getPath(), f.url.getPath())) {
+
+ getUncPath0();
+ f.getUncPath0();
+
+ if (canon.equalsIgnoreCase(f.canon)) {
+ try {
+ ret = getAddress().equals(f.getAddress());
+ } catch( UnknownHostException uhe ) {
+ ret = getServer().equalsIgnoreCase(f.getServer());
+ }
+ return ret;
+ }
+ }
+ }
+
+ return false;
+ }
+/*
+ public boolean equals( Object obj ) {
return obj instanceof SmbFile && obj.hashCode() == hashCode();
}
+*/
/**
* Returns the string representation of this SmbFile object. This will
DcerpcHandle handle;
ACE[] aces;
- rpc = new MsrpcShareGetInfo(url.getHost(), getShare());
- handle = DcerpcHandle.getHandle("ncacn_np:" + url.getHost() + "[\\PIPE\\srvsvc]", auth);
+ resolveDfs(null);
+ String server = getServerWithDfs();
+
+ rpc = new MsrpcShareGetInfo(server, tree.share);
+ handle = DcerpcHandle.getHandle("ncacn_np:" + server + "[\\PIPE\\srvsvc]", auth);
try {
handle.sendrecv(rpc);
public ACE[] getSecurity() throws IOException {
return getSecurity(false);
}
+
}
}
private int uid;
- private Vector trees;
+ Vector trees;
private boolean sessionSetup;
// Transport parameters allows trans to be removed from CONNECTIONS
private UniAddress address;
+++ /dev/null
-/* jcifs smb client library in Java
- * Copyright (C) 2000 "Michael B. Allen" <jcifs at samba dot org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-package jcifs.smb;
-
-import java.util.Vector;
-import java.util.Enumeration;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import jcifs.Config;
-import jcifs.UniAddress;
-import jcifs.netbios.NbtAddress;
-
-/**
- * The class represents a user's session established with an SMB/CIFS
- * server. This class is used internally to the jCIFS library however
- * applications may wish to authenticate aribrary user credentials
- * with the <tt>logon</tt> method. It is noteworthy that jCIFS does not
- * support DCE/RPC at this time and therefore does not use the NETLOGON
- * procedure. Instead, it simply performs a "tree connect" to IPC$ using
- * the supplied credentials. This is only a subset of the NETLOGON procedure
- * but is achives the same effect.
-
-Note that it is possible to change the resource against which clients
-are authenticated to be something other than <tt>IPC$</tt> using the
-<tt>jcifs.smb.client.logonShare</tt> property. This can be used to
-provide simple group based access control. For example, one could setup
-the NTLM HTTP Filter with the <tt>jcifs.smb.client.domainController</tt>
-init parameter set to the name of the server used for authentication. On
-that host, create a share called JCIFSAUTH and adjust the access control
-list for that share to permit only the clients that should have access to
-the target website. Finally, set the <tt>jcifs.smb.client.logonShare</tt>
-to JCIFSAUTH. This should restrict access to only those clients that have
-access to the JCIFSAUTH share. The access control on that share can be
-changed without changing init parameters or reinitializing the webapp.
- */
-
-public final class SmbSession {
-
- private static final String LOGON_SHARE =
- Config.getProperty( "jcifs.smb.client.logonShare", null );
- private static final int LOOKUP_RESP_LIMIT =
- Config.getInt( "jcifs.netbios.lookupRespLimit", 3 );
- private static final String DOMAIN =
- Config.getProperty("jcifs.smb.client.domain", null);
- private static final String USERNAME =
- Config.getProperty("jcifs.smb.client.username", null);
- private static final int CACHE_POLICY =
- Config.getInt( "jcifs.netbios.cachePolicy", 60 * 10 ) * 60; /* 10 hours */
-
- static NbtAddress[] dc_list = null;
- static long dc_list_expiration;
- static int dc_list_counter;
-
- private static NtlmChallenge interrogate( NbtAddress addr ) throws SmbException {
- UniAddress dc = new UniAddress( addr );
- SmbTransport trans = SmbTransport.getSmbTransport( dc, 0 );
- if (USERNAME == null) {
- trans.connect();
- if (SmbTransport.log.level >= 3)
- SmbTransport.log.println(
- "Default credentials (jcifs.smb.client.username/password)" +
- " not specified. SMB signing may not work propertly." +
- " Skipping DC interrogation." );
- } else {
- SmbSession ssn = trans.getSmbSession( NtlmPasswordAuthentication.DEFAULT );
- ssn.getSmbTree( LOGON_SHARE, null ).treeConnect( null, null );
- }
- return new NtlmChallenge( trans.server.encryptionKey, dc );
- }
- public static NtlmChallenge getChallengeForDomain()
- throws SmbException, UnknownHostException {
- if( DOMAIN == null ) {
- throw new SmbException( "A domain was not specified" );
- }
- synchronized (DOMAIN) {
- long now = System.currentTimeMillis();
-int retry = 1;
-
-do {
- if (dc_list_expiration < now) {
- dc_list_expiration = now + CACHE_POLICY * 1000L;
- NbtAddress[] list = NbtAddress.getAllByName( DOMAIN, 0x1C, null, null );
- if (list != null && list.length > 0) {
- dc_list = list;
- } else { /* keep using the old list */
- dc_list_expiration = now + 1000 * 60 * 15; /* 15 min */
- if (SmbTransport.log.level >= 2) {
- SmbTransport.log.println( "Failed to retrieve DC list from WINS" );
- }
- }
- }
-
- int max = Math.min( dc_list.length, LOOKUP_RESP_LIMIT );
- for (int j = 0; j < max; j++) {
- int i = dc_list_counter++ % max;
- if (dc_list[i] != null) {
- try {
- return interrogate( dc_list[i] );
- } catch (SmbException se) {
- if (SmbTransport.log.level >= 2) {
- SmbTransport.log.println( "Failed validate DC: " + dc_list[i] );
- if (SmbTransport.log.level > 2)
- se.printStackTrace( SmbTransport.log );
- }
- }
- dc_list[i] = null;
- }
- }
-
-/* No DCs found, for retieval of list by expiring it and retry.
- */
- dc_list_expiration = 0;
-} while (retry-- > 0);
-
- dc_list_expiration = now + 1000 * 60 * 15; /* 15 min */
- }
-
- throw new UnknownHostException(
- "Failed to negotiate with a suitable domain controller for " + DOMAIN );
- }
-
- public static byte[] getChallenge( UniAddress dc )
- throws SmbException, UnknownHostException {
- return getChallenge(dc, 0);
- }
-
- public static byte[] getChallenge( UniAddress dc, int port )
- throws SmbException, UnknownHostException {
- SmbTransport trans = SmbTransport.getSmbTransport( dc, port );
- trans.connect();
- return trans.server.encryptionKey;
- }
-/**
- * Authenticate arbitrary credentials represented by the
- * <tt>NtlmPasswordAuthentication</tt> object against the domain controller
- * specified by the <tt>UniAddress</tt> parameter. If the credentials are
- * not accepted, an <tt>SmbAuthException</tt> will be thrown. If an error
- * occurs an <tt>SmbException</tt> will be thrown. If the credentials are
- * valid, the method will return without throwing an exception. See the
- * last <a href="../../../faq.html">FAQ</a> question.
- *
- * See also the <tt>jcifs.smb.client.logonShare</tt> property.
- */
- public static void logon( UniAddress dc,
- NtlmPasswordAuthentication auth ) throws SmbException {
- logon(dc, 0, auth);
- }
-
- public static void logon( UniAddress dc, int port,
- NtlmPasswordAuthentication auth ) throws SmbException {
- SmbTree tree = SmbTransport.getSmbTransport( dc, port ).getSmbSession( auth ).getSmbTree( LOGON_SHARE, null );
- if( LOGON_SHARE == null ) {
- tree.treeConnect( null, null );
- } else {
- Trans2FindFirst2 req = new Trans2FindFirst2( "\\", "*", SmbFile.ATTR_DIRECTORY );
- Trans2FindFirst2Response resp = new Trans2FindFirst2Response();
- tree.send( req, resp );
- }
- }
-
- private int uid;
- private Vector trees;
- private boolean sessionSetup;
- // Transport parameters allows trans to be removed from CONNECTIONS
- private UniAddress address;
- private int port, localPort;
- private InetAddress localAddr;
-
- SmbTransport transport = null;
- NtlmPasswordAuthentication auth;
- long expiration;
-
- SmbSession( UniAddress address, int port,
- InetAddress localAddr, int localPort,
- NtlmPasswordAuthentication auth ) {
- this.address = address;
- this.port = port;
- this.localAddr = localAddr;
- this.localPort = localPort;
- this.auth = auth;
- trees = new Vector();
- }
-
- synchronized SmbTree getSmbTree( String share, String service ) {
- SmbTree t;
-
- if( share == null ) {
- share = "IPC$";
- }
- for( Enumeration e = trees.elements(); e.hasMoreElements(); ) {
- t = (SmbTree)e.nextElement();
- if( t.matches( share, service )) {
- return t;
- }
- }
- t = new SmbTree( this, share, service );
- trees.addElement( t );
- return t;
- }
- boolean matches( NtlmPasswordAuthentication auth ) {
- return this.auth == auth || this.auth.equals( auth );
- }
- synchronized SmbTransport transport() {
- if( transport == null ) {
- transport = SmbTransport.getSmbTransport( address, port, localAddr, localPort );
- }
- return transport;
- }
- void send( ServerMessageBlock request,
- ServerMessageBlock response ) throws SmbException {
- if( response != null ) {
- response.received = false;
- }
-
- synchronized(transport.setupDiscoLock) {
- 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 );
- }
- }
-int x = 0;
- void sessionSetup( ServerMessageBlock andx,
- ServerMessageBlock andxResponse ) throws SmbException {
-synchronized( transport() ) {
- if( sessionSetup ) {
- return;
- }
-
- transport.connect();
-
- /*
- * Session Setup And X Request / Response
- */
-
- if( transport.log.level >= 4 )
- transport.log.println( "sessionSetup: accountName=" + auth.username + ",primaryDomain=" + auth.domain );
-
- SmbComSessionSetupAndX request = new SmbComSessionSetupAndX( this, andx );
- SmbComSessionSetupAndXResponse response = new SmbComSessionSetupAndXResponse( andxResponse );
-
- /* Create SMB signature digest if necessary
- * Only the first SMB_COM_SESSION_SETUP_ANX with non-null or
- * blank password initializes signing.
- */
- if (transport.isSignatureSetupRequired( auth )) {
- if( auth.hashesExternal && NtlmPasswordAuthentication.DEFAULT_PASSWORD != NtlmPasswordAuthentication.BLANK ) {
- /* preauthentication
- */
- transport.getSmbSession( NtlmPasswordAuthentication.DEFAULT ).getSmbTree( LOGON_SHARE, null ).treeConnect( null, null );
- } else {
- request.digest = new SigningDigest( transport, auth );
- }
- }
-
- request.auth = auth;
- transport.send( request, response );
-
- if( response.isLoggedInAsGuest &&
- "GUEST".equalsIgnoreCase( auth.username ) == false) {
- throw new SmbAuthException( NtStatus.NT_STATUS_LOGON_FAILURE );
- }
-
- uid = response.uid;
- sessionSetup = true;
-
- if( request.digest != null ) {
- /* success - install the signing digest */
- transport.digest = request.digest;
- }
-}
- }
- void logoff( boolean inError ) {
-synchronized( transport() ) {
- if( sessionSetup == false ) {
- return;
- }
-
- for( Enumeration e = trees.elements(); e.hasMoreElements(); ) {
- SmbTree t = (SmbTree)e.nextElement();
- t.treeDisconnect( inError );
- }
-
- if( !inError && transport.server.security != ServerMessageBlock.SECURITY_SHARE ) {
-
- /*
- * Logoff And X Request / Response
- */
-
- SmbComLogoffAndX request = new SmbComLogoffAndX( null );
- request.uid = uid;
- try {
- transport.send( request, null );
- } catch( SmbException se ) {
- }
- }
-
- sessionSetup = false;
-}
- }
- public String toString() {
- return "SmbSession[accountName=" + auth.username +
- ",primaryDomain=" + auth.domain +
- ",uid=" + uid +
- ",sessionSetup=" + sessionSetup + "]";
- }
-}
protected int type;
protected String remark;
+ public SmbShareInfo() {
+ }
+ public SmbShareInfo(String netName, int type, String remark)
+ {
+ this.netName = netName;
+ this.type = type;
+ this.remark = remark;
+ }
public String getName() {
return netName;
}
import jcifs.netbios.*;
import jcifs.util.*;
import jcifs.util.transport.*;
+import jcifs.dcerpc.*;
+import jcifs.dcerpc.msrpc.*;
public class SmbTransport extends Transport implements SmbConstants {
static final byte[] BUF = new byte[0xFFFF];
static final SmbComNegotiate NEGOTIATE_REQUEST = new SmbComNegotiate();
static LogStream log = LogStream.getInstance();
+ static HashMap dfsRoots = null;
static synchronized SmbTransport getSmbTransport( UniAddress address, int port ) {
return getSmbTransport( address, port, LADDR, LPORT );
if( req.auth == null ) {
throw new SmbException( resp.errorCode, null );
}
- DfsReferral dr = getDfsReferral( req.auth, req.path );
- referrals.add( dr );
- throw dr;
+
+ DfsReferral[] drs = getDfsReferrals(req.auth, req.path, 1);
+ SmbFile.dfs.insert(req.path, drs[0]);
+ throw drs[0];
case 0x80000005: /* STATUS_BUFFER_OVERFLOW */
break; /* normal for DCERPC named pipes */
default:
/* DFS */
- DfsReferral getDfsReferral( NtlmPasswordAuthentication auth,
- String path ) throws SmbException {
- String subpath, node, host;
- DfsReferral dr = new DfsReferral();
- int p, n, i, s;
- UniAddress addr;
+ /* Split DFS path like \fs1.example.com\root5\link2\foo\bar.txt into at
+ * most 3 components (not including the first index which is always empty):
+ * result[0] = ""
+ * result[1] = "fs1.example.com"
+ * result[2] = "root5"
+ * result[3] = "link2\foo\bar.txt"
+ */
+ void dfsPathSplit(String path, String[] result)
+ {
+ int ri = 0, rlast = result.length - 1;
+ int i = 0, b = 0, len = path.length();
+
+ do {
+ if (ri == rlast) {
+ result[rlast] = path.substring(b);
+ return;
+ }
+ if (i == len || path.charAt(i) == '\\') {
+ result[ri++] = path.substring(b, i);
+ b = i + 1;
+ }
+ } while (i++ < len);
+ while (ri < result.length) {
+ result[ri++] = "";
+ }
+ }
+ DfsReferral[] getDfsReferrals(NtlmPasswordAuthentication auth,
+ String path,
+ int rn) throws SmbException {
SmbTree ipc = getSmbSession( auth ).getSmbTree( "IPC$", null );
Trans2GetDfsReferralResponse resp = new Trans2GetDfsReferralResponse();
ipc.send( new Trans2GetDfsReferral( path ), resp );
- subpath = path.substring( 0, resp.pathConsumed );
- node = resp.referral.node;
- if( subpath.charAt( 0 ) != '\\' ||
- (i = subpath.indexOf( '\\', 1 )) < 2 ||
- (p = subpath.indexOf( '\\', i + 1 )) < (i + 2) ||
- node.charAt( 0 ) != '\\' ||
- (s = node.indexOf( '\\', 1 )) < 2) {
- throw new SmbException( "Invalid DFS path: " + path );
- }
- if ((n = node.indexOf( '\\', s + 1 )) == -1) {
- n = node.length();
+ if (rn == 0 || resp.numReferrals < rn) {
+ rn = resp.numReferrals;
}
- dr.path = subpath.substring( p );
- dr.node = node.substring( 0, n );
- dr.nodepath = node.substring( n );
- dr.server = node.substring( 1, s );
- dr.share = node.substring( s + 1, n );
- dr.resolveHashes = auth.hashesExternal;
+ DfsReferral[] drs = new DfsReferral[rn];
+ String[] arr = new String[4];
+ long expiration = System.currentTimeMillis() + Dfs.TTL * 1000;
+
+ for (int di = 0; di < drs.length; di++) {
+ DfsReferral dr = new DfsReferral();
/* NTLM HTTP Authentication must be re-negotiated
* with challenge from 'server' to access DFS vol. */
- return dr;
+ dr.resolveHashes = auth.hashesExternal;
+ dr.ttl = resp.referrals[di].ttl;
+ dr.expiration = expiration;
+ if (path.equals("")) {
+ dr.server = resp.referrals[di].path.substring(1).toLowerCase();
+ } else {
+ dfsPathSplit(resp.referrals[di].node, arr);
+ dr.server = arr[1];
+ dr.share = arr[2];
+ dr.path = arr[3];
+ }
+ dr.pathConsumed = resp.pathConsumed;
+ drs[di] = dr;
+ }
+
+ return drs;
}
- DfsReferral lookupReferral( String unc ) {
- synchronized( referrals ) {
- DfsReferral dr;
- ListIterator iter = referrals.listIterator();
- int i, len;
+ FileEntry[] getDfsRoots(String domainName, NtlmPasswordAuthentication auth) throws IOException {
+ MsrpcDfsRootEnum rpc;
+ DcerpcHandle handle = null;
+
+ /* Procedure:
+ * Lookup a DC in the target domain
+ * Ask the DC for a referral for the domain (e.g. "\example.com")
+ * Do NetrDfsEnumEx on the server returned in the referral to
+ * get roots in target domain
+ */
- 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;
- }
+ UniAddress dc = UniAddress.getByName(domainName);
+ SmbTransport trans = SmbTransport.getSmbTransport(dc, 0);
+ DfsReferral[] dr = trans.getDfsReferrals(auth, "\\" + domainName, 1);
+
+ handle = DcerpcHandle.getHandle("ncacn_np:" +
+ UniAddress.getByName(dr[0].server).getHostAddress() +
+ "[\\PIPE\\netdfs]", auth);
+ try {
+ rpc = new MsrpcDfsRootEnum(domainName);
+ handle.sendrecv(rpc);
+ if (rpc.retval != 0)
+ throw new SmbException(rpc.retval, true);
+ return rpc.getEntries();
+ } finally {
+ try {
+ handle.close();
+ } catch(IOException ioe) {
+ if (log.level >= 4)
+ ioe.printStackTrace(log);
}
}
-
- return null;
}
}
private static int tree_conn_counter;
private int tid;
- private String share;
+ String share;
String service = "?????";
SmbSession session;
- boolean treeConnected, inDfs;
+ boolean treeConnected, inDfs, inDomainDfs;
int tree_num;
SmbTree( SmbSession session, String share, String service ) {
}
void treeDisconnect( boolean inError ) {
synchronized( session.transport ) {
- if (treeConnected && !inError) {
+ if (treeConnected && !inError && tid != 0) {
try {
send( new SmbComTreeDisconnect(), null );
} catch( SmbException se ) {
}
}
treeConnected = false;
+ inDfs = false;
+ inDomainDfs = false;
}
}
",service=" + service +
",tid=" + tid +
",inDfs=" + inDfs +
+ ",inDomainDfs=" + inDomainDfs +
",treeConnected=" + treeConnected + "]";
}
}
private int serverType;
private int flags;
private int proximity;
- private int ttl;
private int pathOffset;
private int altPathOffset;
private int nodeOffset;
- private String path = null;
private String altPath;
- String node;
+ int ttl;
+ String path = null;
+ String node = null;
int readWireFormat( byte[] buffer, int bufferIndex, int len ) {
int start = bufferIndex;
bufferIndex += 2;
path = readString( buffer, start + pathOffset, len, (flags2 & FLAGS2_UNICODE) != 0);
- node = readString( buffer, start + nodeOffset, len, (flags2 & FLAGS2_UNICODE) != 0);
+ if (nodeOffset > 0)
+ node = readString( buffer, start + nodeOffset, len, (flags2 & FLAGS2_UNICODE) != 0);
} else if( version == 1 ) {
node = readString( buffer, bufferIndex, len, (flags2 & FLAGS2_UNICODE) != 0);
}
int pathConsumed;
int numReferrals;
int flags;
- Referral referral;
+ Referral[] referrals;
Trans2GetDfsReferralResponse() {
subCommand = SmbComTransaction.TRANS2_GET_DFS_REFERRAL;
flags = readInt2( buffer, bufferIndex );
bufferIndex += 4;
- referral = new Referral();
- while( numReferrals-- > 0 ) {
- bufferIndex += referral.readWireFormat( buffer, bufferIndex, len );
- }
- if (referral.path != null && referral.path.charAt( pathConsumed - 1 ) == '\\' ) {
- pathConsumed--;
+ referrals = new Referral[numReferrals];
+ for (int ri = 0; ri < numReferrals; ri++) {
+ referrals[ri] = new Referral();
+ bufferIndex += referrals[ri].readWireFormat( buffer, bufferIndex, len );
}
return bufferIndex - start;
public String toString() {
return new String( "Trans2GetDfsReferralResponse[" +
super.toString() + ",pathConsumed=" + pathConsumed +
- ",numReferrals=" + numReferrals + ",flags=" + flags +
- "," + referral + "]" );
+ ",numReferrals=" + numReferrals + ",flags=" + flags + "]" );
}
}