jcifs-1.2.18e from tgz
authorFelix Schumacher <p0354740@isib001.(none)>
Wed, 6 Aug 2008 14:44:25 +0000 (16:44 +0200)
committerFelix Schumacher <p0354740@isib001.(none)>
Wed, 6 Aug 2008 14:44:25 +0000 (16:44 +0200)
Wed Feb  6 00:05:42 EST 2008
jcifs-1.2.18e released

The SID.getServerSid() method could fail with NetApp servers due to a
"generic" mask values. The mask has been changed to 0x00000001 which
corresponds to an LsaOpenPolicy mask of POLICY_VIEW_LOCAL_INFORMATION.

The LsaPolicyHandle class would not throw an error if the LsarOpenPolicy2
call failed. This has been fixed.

The SmbFile constructor could inappropriately URL decode the authority
component of SMB URLs.

The NTLM HTTP Filter documentation has been updated.

An Invalid state: 4 error has been fixed.

A NetBIOS name service issue caused by Jetdirect printers has been fixed.

An ArrayIndexOutOfBounds exception in the SmbException class has been
fixed.

A NullPointerException in SmbSession.getChallengeForDomain() has been
fixed.

A NullPointerException in NbtAddress related to hosts without adequate
localhost address configuration has been fixed.

An ArrayIndexOutOfBounds exception could be thrown if a server requires
NTLMv2. This exception has been replaced with a more informative one.

The SmbSessionSetup constructor will now compare the challenge and
encryptionKey using Arrays.equals instead of == to satisfy unforseen
use-cases that otherwise trigger an NT_STATUS_ACCESS_VIOLATION.

If a share was unshared while JCIFS was in the middle of reading files
from it, the transport could enter an error state from which it could
not immediately recover if the share was restored. A small change to
SmbTransport.doRecv() fixes this problem.

Tue Jun 26 16:11:31 EDT 2007

The DCERPC bind did not exactly mimic Windows which uses
SMB_COM_{WRITE,READ}_ANDX. We were using TransactNmPipe throughout which
could result in an 'Incorrect function' error when querying the LSA on
a NetApp server. JCIFS now implements the bind exactly like Windows to
help ensure compatibility with other servers.

A minor performance flaw in the DCERPC code was found and fixed.

106 files changed:
README.txt
build.xml
examples/AclCrawler.class [deleted file]
examples/AllocInfo.class [deleted file]
examples/Append.class [deleted file]
examples/AuthListFiles.class [deleted file]
examples/CallNamedPipe.class [deleted file]
examples/CopyTo.class [deleted file]
examples/CountPerms.class [deleted file]
examples/CreateFile.class [deleted file]
examples/Delete.class [deleted file]
examples/Equals.class [deleted file]
examples/Exists.class [deleted file]
examples/FileInfo.class [deleted file]
examples/FileOps.class [deleted file]
examples/FilterFiles$BigFileFilter.class [deleted file]
examples/FilterFiles$ShortFilenameFilter.class [deleted file]
examples/FilterFiles.class [deleted file]
examples/Format.class [deleted file]
examples/Get.class [deleted file]
examples/GetDate.class [deleted file]
examples/GetDfsPath.class [deleted file]
examples/GetGroupMemberSidsFromURL.class [deleted file]
examples/GetLocalGroupMemberSidsFromURL.java [new file with mode: 0644]
examples/GetSecurity.class [deleted file]
examples/GetServerSidFromURL.java [new file with mode: 0644]
examples/GetShareSecurity.class [deleted file]
examples/GetType.class [deleted file]
examples/GetURL.class [deleted file]
examples/GrowWrite.class [deleted file]
examples/HttpURL.class [deleted file]
examples/Interleave$IThread.class [deleted file]
examples/Interleave.class [deleted file]
examples/InterruptTest.class [deleted file]
examples/IsDir.class [deleted file]
examples/LargeListFiles.class [deleted file]
examples/Length.class [deleted file]
examples/List.class [deleted file]
examples/ListACL.class [deleted file]
examples/ListFiles.class [deleted file]
examples/ListTypes.class [deleted file]
examples/Mkdir.class [deleted file]
examples/NodeStatus.class [deleted file]
examples/OpenExclusive.class [deleted file]
examples/PeekNamedPipe$ReceiverThread.class [deleted file]
examples/PeekNamedPipe.class [deleted file]
examples/PipeTalk$ReceiverThread.class [deleted file]
examples/PipeTalk.class [deleted file]
examples/Put.class [deleted file]
examples/Query.class [deleted file]
examples/RenameTo.class [deleted file]
examples/SetAttrs.class [deleted file]
examples/SetTime.class [deleted file]
examples/SidCacheTest.class [deleted file]
examples/SidCrawler.class [deleted file]
examples/SidLookup.class [deleted file]
examples/SlowRead.class [deleted file]
examples/SlowWrite.class [deleted file]
examples/SmbCrawler.class [deleted file]
examples/SmbShell.class [deleted file]
examples/SmbTableFile.class [deleted file]
examples/SmbTableFileRecord.class [deleted file]
examples/SmbThreadTest.class [deleted file]
examples/T2Crawler$CrawlerThread.class [deleted file]
examples/T2Crawler$Semaphore.class [deleted file]
examples/T2Crawler.class [deleted file]
examples/TestRandomAccess$TestRecord.class [deleted file]
examples/TestRandomAccess.class [deleted file]
examples/TestSmbURL.class [deleted file]
examples/TestUnicode.class [deleted file]
examples/ThreadedNbtQuery$QThread.class [deleted file]
examples/ThreadedNbtQuery.class [deleted file]
examples/ThreadedSmbCrawler$DirEntry.class [deleted file]
examples/ThreadedSmbCrawler$SmbCrawlerThread.class [deleted file]
examples/ThreadedSmbCrawler.class [deleted file]
examples/ThreadedUniQuery$QThread.class [deleted file]
examples/ThreadedUniQuery.class [deleted file]
examples/Torture1.class [deleted file]
examples/Torture2.class [deleted file]
examples/TortureTest5.class [deleted file]
examples/TransactNamedPipe.class [deleted file]
examples/URLTest.class [deleted file]
examples/VerifyGuest.class [deleted file]
examples/VerifyIO.class [deleted file]
examples/VerifyReads.class [deleted file]
examples/Worker.class [deleted file]
src/jcifs/dcerpc/msrpc/LsaPolicyHandle.java
src/jcifs/dcerpc/msrpc/MsrpcQueryInformationPolicy.java [new file with mode: 0644]
src/jcifs/dcerpc/msrpc/MsrpcQueryInformationPolicy2.java [deleted file]
src/jcifs/netbios/NameServiceClient.java
src/jcifs/netbios/NameServiceClient.java-2008-02-05 [new file with mode: 0644]
src/jcifs/netbios/NbtAddress.java
src/jcifs/smb/.SmbConstants.java.swp [deleted file]
src/jcifs/smb/DosError.java
src/jcifs/smb/Handler.java
src/jcifs/smb/NtlmPasswordAuthentication.java
src/jcifs/smb/NtlmPasswordAuthentication.java.orig [new file with mode: 0644]
src/jcifs/smb/SID.java
src/jcifs/smb/SigningDigest.java
src/jcifs/smb/SmbComSessionSetupAndX.java
src/jcifs/smb/SmbConstants.java
src/jcifs/smb/SmbException.java
src/jcifs/smb/SmbSession.java
src/jcifs/smb/SmbSession.java.orig [new file with mode: 0644]
src/jcifs/smb/SmbTransport.java
src/jcifs/util/transport/Transport.java

index 15693fc..68fc403 100644 (file)
@@ -1,34 +1,44 @@
-Wed Aug 15 12:47:55 EDT 2007
-jcifs-1.2.17 released 
+Wed Feb  6 00:05:42 EST 2008
+jcifs-1.2.18e released
 
-A try/catch that was accedentally added in a previous release has been
-removed.
+The SID.getServerSid() method could fail with NetApp servers due to a
+"generic" mask values. The mask has been changed to 0x00000001 which
+corresponds to an LsaOpenPolicy mask of POLICY_VIEW_LOCAL_INFORMATION.
 
-Thu Aug 2 12:00:00 EDT 2007
-jcifs-1.2.16 released
+The LsaPolicyHandle class would not throw an error if the LsarOpenPolicy2
+call failed. This has been fixed.
 
-With this release, JCIFS now supports domain-based DFS. With
-domain-based DFS, clients access DFS roots under the DNS domain name
-like \\example.com\dfs\foo so that users do not need to remember server
-names. However, for clients to work with these DFS roots they have to
-be prepared to connect to each domain controller as necessary to find
-the target share and successfully authenticate. JCIFS now includes this
-retry logic. JCIFS will also do something that it seems even Windows
-clients do not do - if you list the shares of a domain (e.g. (new
-SmbFile("smb://example.com/")).listFiles()), JCIFS will build a merged
-list of all shares on all domain controllers.
+The SmbFile constructor could inappropriately URL decode the authority
+component of SMB URLs.
 
-Note that these changes are fairly significant. Whenever JCIFS tries to
-connect to a server this new logic is used. So if anyone notices anything
-out of the ordinary please report it to the JCIFS mailaing list.
+The NTLM HTTP Filter documentation has been updated.
 
-Mon Jul 16 13:26:26 EDT 2007
-jcifs-1.2.15 released
+An Invalid state: 4 error has been fixed.
 
-This release includes some significant changes. Most of these changes
-are related to NetApp compatibility. The changes in this release are:
+A NetBIOS name service issue caused by Jetdirect printers has been fixed.
 
-An SMB signing failure related to DFS has been fixed.
+An ArrayIndexOutOfBounds exception in the SmbException class has been
+fixed.
+
+A NullPointerException in SmbSession.getChallengeForDomain() has been
+fixed.
+
+A NullPointerException in NbtAddress related to hosts without adequate
+localhost address configuration has been fixed.
+
+An ArrayIndexOutOfBounds exception could be thrown if a server requires
+NTLMv2. This exception has been replaced with a more informative one.
+
+The SmbSessionSetup constructor will now compare the challenge and
+encryptionKey using Arrays.equals instead of == to satisfy unforseen
+use-cases that otherwise trigger an NT_STATUS_ACCESS_VIOLATION.
+
+If a share was unshared while JCIFS was in the middle of reading files
+from it, the transport could enter an error state from which it could
+not immediately recover if the share was restored. A small change to
+SmbTransport.doRecv() fixes this problem.
+
+Tue Jun 26 16:11:31 EDT 2007
 
 The DCERPC bind did not exactly mimic Windows which uses
 SMB_COM_{WRITE,READ}_ANDX. We were using TransactNmPipe throughout which
@@ -36,21 +46,6 @@ could result in an 'Incorrect function' error when querying the LSA on
 a NetApp server. JCIFS now implements the bind exactly like Windows to
 help ensure compatibility with other servers.
 
-Other changes related to NetApp compatibility include falling back to
-SamrConnect2 if an DCERPC_FAULT_OP_RNG_ERROR error occurs, more closely
-mimicing the SMB_COM_NT_CREATE_ANDX "extended" response, adjusting various
-RPC handle operation access masks, uncommenting some padding code that
-was commented out for what appeared to be a NetWare problem, disabling
-some logic to used port 139 if the jcifs.netbios.hostname was set and
-finally adding code to include LsarQosInfo structures in the MSRPC bind.
-
-Some new error code information has been added.
-
-Constants for common SIDs have been added to the SID class.
-
-The SID.getGroupMemberSids() method will now return an empty SID array
-if the SID is not of type SID_TYPE_DOM_GRP or SID_TYPE_ALIAS.
-
 A minor performance flaw in the DCERPC code was found and fixed.
 
 Wed Jun 20 13:09:10 EDT 2007
index 78468f7..cc52003 100644 (file)
--- a/build.xml
+++ b/build.xml
@@ -1,7 +1,7 @@
 <project name="jcifs" default="usage" basedir=".">
 
-    <property name="version" value="1.2.17"/>
-    <property name="reldate" value="Aug 15, 2007"/>
+    <property name="version" value="1.2.18e"/>
+    <property name="reldate" value="Feb 6, 2008"/>
 
     <target name="usage">
         <echo>
diff --git a/examples/AclCrawler.class b/examples/AclCrawler.class
deleted file mode 100644 (file)
index c12c07a..0000000
Binary files a/examples/AclCrawler.class and /dev/null differ
diff --git a/examples/AllocInfo.class b/examples/AllocInfo.class
deleted file mode 100644 (file)
index d052675..0000000
Binary files a/examples/AllocInfo.class and /dev/null differ
diff --git a/examples/Append.class b/examples/Append.class
deleted file mode 100644 (file)
index 584b1f0..0000000
Binary files a/examples/Append.class and /dev/null differ
diff --git a/examples/AuthListFiles.class b/examples/AuthListFiles.class
deleted file mode 100644 (file)
index 851ae58..0000000
Binary files a/examples/AuthListFiles.class and /dev/null differ
diff --git a/examples/CallNamedPipe.class b/examples/CallNamedPipe.class
deleted file mode 100644 (file)
index 1378730..0000000
Binary files a/examples/CallNamedPipe.class and /dev/null differ
diff --git a/examples/CopyTo.class b/examples/CopyTo.class
deleted file mode 100644 (file)
index 1eec536..0000000
Binary files a/examples/CopyTo.class and /dev/null differ
diff --git a/examples/CountPerms.class b/examples/CountPerms.class
deleted file mode 100644 (file)
index 6632e6e..0000000
Binary files a/examples/CountPerms.class and /dev/null differ
diff --git a/examples/CreateFile.class b/examples/CreateFile.class
deleted file mode 100644 (file)
index 9ae7ab1..0000000
Binary files a/examples/CreateFile.class and /dev/null differ
diff --git a/examples/Delete.class b/examples/Delete.class
deleted file mode 100644 (file)
index b52be49..0000000
Binary files a/examples/Delete.class and /dev/null differ
diff --git a/examples/Equals.class b/examples/Equals.class
deleted file mode 100644 (file)
index d1ea38a..0000000
Binary files a/examples/Equals.class and /dev/null differ
diff --git a/examples/Exists.class b/examples/Exists.class
deleted file mode 100644 (file)
index 9f03ca4..0000000
Binary files a/examples/Exists.class and /dev/null differ
diff --git a/examples/FileInfo.class b/examples/FileInfo.class
deleted file mode 100644 (file)
index fbdcf11..0000000
Binary files a/examples/FileInfo.class and /dev/null differ
diff --git a/examples/FileOps.class b/examples/FileOps.class
deleted file mode 100644 (file)
index 9a0e176..0000000
Binary files a/examples/FileOps.class and /dev/null differ
diff --git a/examples/FilterFiles$BigFileFilter.class b/examples/FilterFiles$BigFileFilter.class
deleted file mode 100644 (file)
index 1cd1710..0000000
Binary files a/examples/FilterFiles$BigFileFilter.class and /dev/null differ
diff --git a/examples/FilterFiles$ShortFilenameFilter.class b/examples/FilterFiles$ShortFilenameFilter.class
deleted file mode 100644 (file)
index 0b43d22..0000000
Binary files a/examples/FilterFiles$ShortFilenameFilter.class and /dev/null differ
diff --git a/examples/FilterFiles.class b/examples/FilterFiles.class
deleted file mode 100644 (file)
index e8f82a5..0000000
Binary files a/examples/FilterFiles.class and /dev/null differ
diff --git a/examples/Format.class b/examples/Format.class
deleted file mode 100644 (file)
index 998801f..0000000
Binary files a/examples/Format.class and /dev/null differ
diff --git a/examples/Get.class b/examples/Get.class
deleted file mode 100644 (file)
index 8192c4a..0000000
Binary files a/examples/Get.class and /dev/null differ
diff --git a/examples/GetDate.class b/examples/GetDate.class
deleted file mode 100644 (file)
index 8a82eaa..0000000
Binary files a/examples/GetDate.class and /dev/null differ
diff --git a/examples/GetDfsPath.class b/examples/GetDfsPath.class
deleted file mode 100644 (file)
index 751b59a..0000000
Binary files a/examples/GetDfsPath.class and /dev/null differ
diff --git a/examples/GetGroupMemberSidsFromURL.class b/examples/GetGroupMemberSidsFromURL.class
deleted file mode 100644 (file)
index 5334b1f..0000000
Binary files a/examples/GetGroupMemberSidsFromURL.class and /dev/null differ
diff --git a/examples/GetLocalGroupMemberSidsFromURL.java b/examples/GetLocalGroupMemberSidsFromURL.java
new file mode 100644 (file)
index 0000000..0a546ed
--- /dev/null
@@ -0,0 +1,34 @@
+import java.util.*;
+import jcifs.smb.*;
+
+public class GetLocalGroupMemberSidsFromURL {
+
+    public static void main( String[] argv ) throws Exception {
+        if (argv.length < 1) {
+            System.err.println("usage: GetLocalGroupMemberSidsFromURL <smburl>");
+            System.exit(1);
+        }
+
+        SmbFile file = new SmbFile(argv[0]);
+        String server = file.getServer();
+        NtlmPasswordAuthentication auth = (NtlmPasswordAuthentication)file.getPrincipal();
+        ACE[] security = file.getSecurity(true);
+
+        SID serverSid = SID.getServerSid(server, auth);
+
+        for (int ai = 0; ai < security.length; ai++) {
+            ACE ace = security[ai];
+            SID sid = ace.getSID();
+
+            if (sid.getType() == SID.SID_TYPE_ALIAS && serverSid.equals(sid.getDomainSid())) {
+                System.out.println(sid.toString() + " (" + sid.toDisplayString() + ") members:");
+
+                SID[] mems = sid.getGroupMemberSids(server, auth, SID.SID_FLAG_RESOLVE_SIDS);
+                for (int mi = 0; mi < mems.length; mi++) {
+                    SID mem = mems[mi];
+                    System.out.println("  " + mem.getType() + " " + mem.toDisplayString());
+                }
+            }
+        }
+    }
+}
diff --git a/examples/GetSecurity.class b/examples/GetSecurity.class
deleted file mode 100644 (file)
index 0f1b2d2..0000000
Binary files a/examples/GetSecurity.class and /dev/null differ
diff --git a/examples/GetServerSidFromURL.java b/examples/GetServerSidFromURL.java
new file mode 100644 (file)
index 0000000..b55678e
--- /dev/null
@@ -0,0 +1,20 @@
+import java.util.*;
+import jcifs.smb.*;
+
+public class GetServerSidFromURL {
+
+    public static void main( String[] argv ) throws Exception {
+        if (argv.length < 1) {
+            System.err.println("usage: GetServerSidFromURL <smburl>");
+            System.exit(1);
+        }
+
+        SmbFile file = new SmbFile(argv[0]);
+        String server = file.getServer();
+        NtlmPasswordAuthentication auth = (NtlmPasswordAuthentication)file.getPrincipal();
+
+        SID serverSid = SID.getServerSid(server, auth);
+
+        System.out.println(serverSid);
+    }
+}
diff --git a/examples/GetShareSecurity.class b/examples/GetShareSecurity.class
deleted file mode 100644 (file)
index 6d0f992..0000000
Binary files a/examples/GetShareSecurity.class and /dev/null differ
diff --git a/examples/GetType.class b/examples/GetType.class
deleted file mode 100644 (file)
index 1028177..0000000
Binary files a/examples/GetType.class and /dev/null differ
diff --git a/examples/GetURL.class b/examples/GetURL.class
deleted file mode 100644 (file)
index e473c42..0000000
Binary files a/examples/GetURL.class and /dev/null differ
diff --git a/examples/GrowWrite.class b/examples/GrowWrite.class
deleted file mode 100644 (file)
index 2d0ecbb..0000000
Binary files a/examples/GrowWrite.class and /dev/null differ
diff --git a/examples/HttpURL.class b/examples/HttpURL.class
deleted file mode 100644 (file)
index 55faf3c..0000000
Binary files a/examples/HttpURL.class and /dev/null differ
diff --git a/examples/Interleave$IThread.class b/examples/Interleave$IThread.class
deleted file mode 100644 (file)
index 12d7d51..0000000
Binary files a/examples/Interleave$IThread.class and /dev/null differ
diff --git a/examples/Interleave.class b/examples/Interleave.class
deleted file mode 100644 (file)
index 4ea28d5..0000000
Binary files a/examples/Interleave.class and /dev/null differ
diff --git a/examples/InterruptTest.class b/examples/InterruptTest.class
deleted file mode 100644 (file)
index 8daf426..0000000
Binary files a/examples/InterruptTest.class and /dev/null differ
diff --git a/examples/IsDir.class b/examples/IsDir.class
deleted file mode 100644 (file)
index 712a60e..0000000
Binary files a/examples/IsDir.class and /dev/null differ
diff --git a/examples/LargeListFiles.class b/examples/LargeListFiles.class
deleted file mode 100644 (file)
index 83f6e76..0000000
Binary files a/examples/LargeListFiles.class and /dev/null differ
diff --git a/examples/Length.class b/examples/Length.class
deleted file mode 100644 (file)
index b096ceb..0000000
Binary files a/examples/Length.class and /dev/null differ
diff --git a/examples/List.class b/examples/List.class
deleted file mode 100644 (file)
index 2d2e7b0..0000000
Binary files a/examples/List.class and /dev/null differ
diff --git a/examples/ListACL.class b/examples/ListACL.class
deleted file mode 100644 (file)
index 6c591f9..0000000
Binary files a/examples/ListACL.class and /dev/null differ
diff --git a/examples/ListFiles.class b/examples/ListFiles.class
deleted file mode 100644 (file)
index 190cd04..0000000
Binary files a/examples/ListFiles.class and /dev/null differ
diff --git a/examples/ListTypes.class b/examples/ListTypes.class
deleted file mode 100644 (file)
index 6da499c..0000000
Binary files a/examples/ListTypes.class and /dev/null differ
diff --git a/examples/Mkdir.class b/examples/Mkdir.class
deleted file mode 100644 (file)
index 4c96536..0000000
Binary files a/examples/Mkdir.class and /dev/null differ
diff --git a/examples/NodeStatus.class b/examples/NodeStatus.class
deleted file mode 100644 (file)
index 12e8052..0000000
Binary files a/examples/NodeStatus.class and /dev/null differ
diff --git a/examples/OpenExclusive.class b/examples/OpenExclusive.class
deleted file mode 100644 (file)
index 1802220..0000000
Binary files a/examples/OpenExclusive.class and /dev/null differ
diff --git a/examples/PeekNamedPipe$ReceiverThread.class b/examples/PeekNamedPipe$ReceiverThread.class
deleted file mode 100644 (file)
index 642652c..0000000
Binary files a/examples/PeekNamedPipe$ReceiverThread.class and /dev/null differ
diff --git a/examples/PeekNamedPipe.class b/examples/PeekNamedPipe.class
deleted file mode 100644 (file)
index dcbf77f..0000000
Binary files a/examples/PeekNamedPipe.class and /dev/null differ
diff --git a/examples/PipeTalk$ReceiverThread.class b/examples/PipeTalk$ReceiverThread.class
deleted file mode 100644 (file)
index d05ca7a..0000000
Binary files a/examples/PipeTalk$ReceiverThread.class and /dev/null differ
diff --git a/examples/PipeTalk.class b/examples/PipeTalk.class
deleted file mode 100644 (file)
index d297503..0000000
Binary files a/examples/PipeTalk.class and /dev/null differ
diff --git a/examples/Put.class b/examples/Put.class
deleted file mode 100644 (file)
index 43b1e70..0000000
Binary files a/examples/Put.class and /dev/null differ
diff --git a/examples/Query.class b/examples/Query.class
deleted file mode 100644 (file)
index 0112790..0000000
Binary files a/examples/Query.class and /dev/null differ
diff --git a/examples/RenameTo.class b/examples/RenameTo.class
deleted file mode 100644 (file)
index c169e35..0000000
Binary files a/examples/RenameTo.class and /dev/null differ
diff --git a/examples/SetAttrs.class b/examples/SetAttrs.class
deleted file mode 100644 (file)
index d36bada..0000000
Binary files a/examples/SetAttrs.class and /dev/null differ
diff --git a/examples/SetTime.class b/examples/SetTime.class
deleted file mode 100644 (file)
index 79b5e36..0000000
Binary files a/examples/SetTime.class and /dev/null differ
diff --git a/examples/SidCacheTest.class b/examples/SidCacheTest.class
deleted file mode 100644 (file)
index fd2890b..0000000
Binary files a/examples/SidCacheTest.class and /dev/null differ
diff --git a/examples/SidCrawler.class b/examples/SidCrawler.class
deleted file mode 100644 (file)
index ba712c5..0000000
Binary files a/examples/SidCrawler.class and /dev/null differ
diff --git a/examples/SidLookup.class b/examples/SidLookup.class
deleted file mode 100644 (file)
index 69d1103..0000000
Binary files a/examples/SidLookup.class and /dev/null differ
diff --git a/examples/SlowRead.class b/examples/SlowRead.class
deleted file mode 100644 (file)
index de72174..0000000
Binary files a/examples/SlowRead.class and /dev/null differ
diff --git a/examples/SlowWrite.class b/examples/SlowWrite.class
deleted file mode 100644 (file)
index 84a1cff..0000000
Binary files a/examples/SlowWrite.class and /dev/null differ
diff --git a/examples/SmbCrawler.class b/examples/SmbCrawler.class
deleted file mode 100644 (file)
index efdb5e3..0000000
Binary files a/examples/SmbCrawler.class and /dev/null differ
diff --git a/examples/SmbShell.class b/examples/SmbShell.class
deleted file mode 100644 (file)
index b9096fa..0000000
Binary files a/examples/SmbShell.class and /dev/null differ
diff --git a/examples/SmbTableFile.class b/examples/SmbTableFile.class
deleted file mode 100644 (file)
index c1bfe46..0000000
Binary files a/examples/SmbTableFile.class and /dev/null differ
diff --git a/examples/SmbTableFileRecord.class b/examples/SmbTableFileRecord.class
deleted file mode 100644 (file)
index b5d68ff..0000000
Binary files a/examples/SmbTableFileRecord.class and /dev/null differ
diff --git a/examples/SmbThreadTest.class b/examples/SmbThreadTest.class
deleted file mode 100644 (file)
index 6acf867..0000000
Binary files a/examples/SmbThreadTest.class and /dev/null differ
diff --git a/examples/T2Crawler$CrawlerThread.class b/examples/T2Crawler$CrawlerThread.class
deleted file mode 100644 (file)
index 0b40e5c..0000000
Binary files a/examples/T2Crawler$CrawlerThread.class and /dev/null differ
diff --git a/examples/T2Crawler$Semaphore.class b/examples/T2Crawler$Semaphore.class
deleted file mode 100644 (file)
index af3b771..0000000
Binary files a/examples/T2Crawler$Semaphore.class and /dev/null differ
diff --git a/examples/T2Crawler.class b/examples/T2Crawler.class
deleted file mode 100644 (file)
index 4176b41..0000000
Binary files a/examples/T2Crawler.class and /dev/null differ
diff --git a/examples/TestRandomAccess$TestRecord.class b/examples/TestRandomAccess$TestRecord.class
deleted file mode 100644 (file)
index 872eb31..0000000
Binary files a/examples/TestRandomAccess$TestRecord.class and /dev/null differ
diff --git a/examples/TestRandomAccess.class b/examples/TestRandomAccess.class
deleted file mode 100644 (file)
index 5fdf0df..0000000
Binary files a/examples/TestRandomAccess.class and /dev/null differ
diff --git a/examples/TestSmbURL.class b/examples/TestSmbURL.class
deleted file mode 100644 (file)
index d73dd32..0000000
Binary files a/examples/TestSmbURL.class and /dev/null differ
diff --git a/examples/TestUnicode.class b/examples/TestUnicode.class
deleted file mode 100644 (file)
index 92304e8..0000000
Binary files a/examples/TestUnicode.class and /dev/null differ
diff --git a/examples/ThreadedNbtQuery$QThread.class b/examples/ThreadedNbtQuery$QThread.class
deleted file mode 100644 (file)
index 1259b6d..0000000
Binary files a/examples/ThreadedNbtQuery$QThread.class and /dev/null differ
diff --git a/examples/ThreadedNbtQuery.class b/examples/ThreadedNbtQuery.class
deleted file mode 100644 (file)
index 0d21e06..0000000
Binary files a/examples/ThreadedNbtQuery.class and /dev/null differ
diff --git a/examples/ThreadedSmbCrawler$DirEntry.class b/examples/ThreadedSmbCrawler$DirEntry.class
deleted file mode 100644 (file)
index f849d93..0000000
Binary files a/examples/ThreadedSmbCrawler$DirEntry.class and /dev/null differ
diff --git a/examples/ThreadedSmbCrawler$SmbCrawlerThread.class b/examples/ThreadedSmbCrawler$SmbCrawlerThread.class
deleted file mode 100644 (file)
index a95e988..0000000
Binary files a/examples/ThreadedSmbCrawler$SmbCrawlerThread.class and /dev/null differ
diff --git a/examples/ThreadedSmbCrawler.class b/examples/ThreadedSmbCrawler.class
deleted file mode 100644 (file)
index e0747bf..0000000
Binary files a/examples/ThreadedSmbCrawler.class and /dev/null differ
diff --git a/examples/ThreadedUniQuery$QThread.class b/examples/ThreadedUniQuery$QThread.class
deleted file mode 100644 (file)
index 02d02e0..0000000
Binary files a/examples/ThreadedUniQuery$QThread.class and /dev/null differ
diff --git a/examples/ThreadedUniQuery.class b/examples/ThreadedUniQuery.class
deleted file mode 100644 (file)
index 08632f7..0000000
Binary files a/examples/ThreadedUniQuery.class and /dev/null differ
diff --git a/examples/Torture1.class b/examples/Torture1.class
deleted file mode 100644 (file)
index 72d5f77..0000000
Binary files a/examples/Torture1.class and /dev/null differ
diff --git a/examples/Torture2.class b/examples/Torture2.class
deleted file mode 100644 (file)
index e688b4f..0000000
Binary files a/examples/Torture2.class and /dev/null differ
diff --git a/examples/TortureTest5.class b/examples/TortureTest5.class
deleted file mode 100644 (file)
index cadf7c2..0000000
Binary files a/examples/TortureTest5.class and /dev/null differ
diff --git a/examples/TransactNamedPipe.class b/examples/TransactNamedPipe.class
deleted file mode 100644 (file)
index faea615..0000000
Binary files a/examples/TransactNamedPipe.class and /dev/null differ
diff --git a/examples/URLTest.class b/examples/URLTest.class
deleted file mode 100644 (file)
index 5263435..0000000
Binary files a/examples/URLTest.class and /dev/null differ
diff --git a/examples/VerifyGuest.class b/examples/VerifyGuest.class
deleted file mode 100644 (file)
index 6a8ce08..0000000
Binary files a/examples/VerifyGuest.class and /dev/null differ
diff --git a/examples/VerifyIO.class b/examples/VerifyIO.class
deleted file mode 100644 (file)
index 1168477..0000000
Binary files a/examples/VerifyIO.class and /dev/null differ
diff --git a/examples/VerifyReads.class b/examples/VerifyReads.class
deleted file mode 100644 (file)
index ff0d0a1..0000000
Binary files a/examples/VerifyReads.class and /dev/null differ
diff --git a/examples/Worker.class b/examples/Worker.class
deleted file mode 100644 (file)
index 25fa3b2..0000000
Binary files a/examples/Worker.class and /dev/null differ
index 90ce2c0..b25592f 100644 (file)
@@ -21,6 +21,8 @@ package jcifs.dcerpc.msrpc;
 
 import java.io.IOException;
 
+import jcifs.smb.SmbException;
+
 import jcifs.dcerpc.*;
 
 public class LsaPolicyHandle extends rpc.policy_handle {
@@ -30,6 +32,8 @@ public class LsaPolicyHandle extends rpc.policy_handle {
             server = "\\\\";
         MsrpcLsarOpenPolicy2 rpc = new MsrpcLsarOpenPolicy2(server, access, this);
         handle.sendrecv(rpc);
+        if (rpc.retval != 0)
+            throw new SmbException(rpc.retval, false);
     }
 
     public void close() throws IOException {
diff --git a/src/jcifs/dcerpc/msrpc/MsrpcQueryInformationPolicy.java b/src/jcifs/dcerpc/msrpc/MsrpcQueryInformationPolicy.java
new file mode 100644 (file)
index 0000000..476380d
--- /dev/null
@@ -0,0 +1,34 @@
+/* jcifs msrpc client library in Java
+ * Copyright (C) 2007  "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.*;
+import jcifs.dcerpc.ndr.*;
+
+public class MsrpcQueryInformationPolicy extends lsarpc.LsarQueryInformationPolicy {
+
+    public MsrpcQueryInformationPolicy(LsaPolicyHandle policyHandle,
+                    short level,
+                    NdrObject info) {
+        super(policyHandle, level, info);
+        ptype = 0;
+        flags = DCERPC_FIRST_FRAG | DCERPC_LAST_FRAG;
+    }
+}
diff --git a/src/jcifs/dcerpc/msrpc/MsrpcQueryInformationPolicy2.java b/src/jcifs/dcerpc/msrpc/MsrpcQueryInformationPolicy2.java
deleted file mode 100644 (file)
index 7fe1919..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/* jcifs msrpc client library in Java
- * Copyright (C) 2007  "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.*;
-import jcifs.dcerpc.ndr.*;
-
-public class MsrpcQueryInformationPolicy2 extends lsarpc.LsarQueryInformationPolicy2 {
-
-    public MsrpcQueryInformationPolicy2(LsaPolicyHandle policyHandle,
-                    short level,
-                    NdrObject info) {
-        super(policyHandle, level, info);
-        ptype = 0;
-        flags = DCERPC_FIRST_FRAG | DCERPC_LAST_FRAG;
-    }
-}
index 00f4d3a..93cf76c 100644 (file)
@@ -237,10 +237,21 @@ class NameServiceClient implements Runnable {
                         }
                     }
 
-                    response.wait( timeout );
+                    long start = System.currentTimeMillis();
+                    while (timeout > 0) {
+                        response.wait( timeout );
+
+                        /* JetDirect printer can respond to regular broadcast query
+                         * with node status so we need to check to make sure that
+                         * the record type matches the question type and if not,
+                         * loop around and try again.
+                         */
+                        if (response.received && request.questionType == response.recordType)
+                            return;
 
-                    if (response.received)
-                        return;
+                        response.received = false;
+                        timeout -= System.currentTimeMillis() - start;
+                    }
 
                 } catch( InterruptedException ie ) {
                 } finally {
diff --git a/src/jcifs/netbios/NameServiceClient.java-2008-02-05 b/src/jcifs/netbios/NameServiceClient.java-2008-02-05
new file mode 100644 (file)
index 0000000..00f4d3a
--- /dev/null
@@ -0,0 +1,431 @@
+/* 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.netbios;
+
+import java.net.*;
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+import jcifs.Config;
+import jcifs.util.Hexdump;
+import jcifs.util.LogStream;
+
+class NameServiceClient implements Runnable {
+
+    static final int DEFAULT_SO_TIMEOUT = 5000;
+    static final int DEFAULT_RCV_BUF_SIZE = 576;
+    static final int DEFAULT_SND_BUF_SIZE = 576;
+    static final int NAME_SERVICE_UDP_PORT = 137;
+    static final int DEFAULT_RETRY_COUNT = 2;
+    static final int DEFAULT_RETRY_TIMEOUT = 3000;
+
+    static final int RESOLVER_LMHOSTS = 1;
+    static final int RESOLVER_BCAST   = 2;
+    static final int RESOLVER_WINS    = 3;
+
+    private static final int SND_BUF_SIZE = Config.getInt( "jcifs.netbios.snd_buf_size", DEFAULT_SND_BUF_SIZE );
+    private static final int RCV_BUF_SIZE = Config.getInt( "jcifs.netbios.rcv_buf_size", DEFAULT_RCV_BUF_SIZE );
+    private static final int SO_TIMEOUT = Config.getInt( "jcifs.netbios.soTimeout", DEFAULT_SO_TIMEOUT );
+    private static final int RETRY_COUNT = Config.getInt( "jcifs.netbios.retryCount", DEFAULT_RETRY_COUNT );
+    private static final int RETRY_TIMEOUT = Config.getInt( "jcifs.netbios.retryTimeout", DEFAULT_RETRY_TIMEOUT);
+    private static final int LPORT = Config.getInt( "jcifs.netbios.lport", 0 );
+    private static final InetAddress LADDR = Config.getInetAddress( "jcifs.netbios.laddr", null );
+    private static final String RO = Config.getProperty( "jcifs.resolveOrder" );
+
+    private static LogStream log = LogStream.getInstance();
+
+    private final Object LOCK = new Object();
+
+    private int lport, closeTimeout;
+    private byte[] snd_buf, rcv_buf;
+    private DatagramSocket socket;
+    private DatagramPacket in, out;
+    private HashMap responseTable = new HashMap();
+    private Thread thread;
+    private int nextNameTrnId = 0;
+    private int[] resolveOrder;
+
+    InetAddress laddr, baddr;
+
+    NameServiceClient() {
+        this( LPORT, LADDR );
+    }
+    NameServiceClient( int lport, InetAddress laddr ) {
+        this.lport = lport;
+        this.laddr = laddr;
+
+        try {
+            baddr = Config.getInetAddress( "jcifs.netbios.baddr",
+                        InetAddress.getByName( "255.255.255.255" ));
+        } catch( UnknownHostException uhe ) {
+        }
+
+        snd_buf = new byte[SND_BUF_SIZE];
+        rcv_buf = new byte[RCV_BUF_SIZE];
+        out = new DatagramPacket( snd_buf, SND_BUF_SIZE, baddr, NAME_SERVICE_UDP_PORT );
+        in  = new DatagramPacket( rcv_buf, RCV_BUF_SIZE );
+
+        if( RO == null || RO.length() == 0 ) {
+
+            /* No resolveOrder has been specified, use the
+             * default which is LMHOSTS,WINS,BCAST,DNS or just
+             * LMHOSTS,BCAST,DNS if jcifs.netbios.wins has not
+             * been specified.
+             */
+
+            if( NbtAddress.getWINSAddress() == null ) {
+                resolveOrder = new int[2];
+                resolveOrder[0] = RESOLVER_LMHOSTS;
+                resolveOrder[1] = RESOLVER_BCAST;
+            } else {
+                resolveOrder = new int[3];
+                resolveOrder[0] = RESOLVER_LMHOSTS;
+                resolveOrder[1] = RESOLVER_WINS;
+                resolveOrder[2] = RESOLVER_BCAST;
+            }
+        } else {
+            int[] tmp = new int[3];
+            StringTokenizer st = new StringTokenizer( RO, "," );
+            int i = 0;
+            while( st.hasMoreTokens() ) {
+                String s = st.nextToken().trim();
+                if( s.equalsIgnoreCase( "LMHOSTS" )) {
+                    tmp[i++] = RESOLVER_LMHOSTS;
+                } else if( s.equalsIgnoreCase( "WINS" )) {
+                    if( NbtAddress.getWINSAddress() == null ) {
+                        if( log.level > 1 ) {
+                            log.println( "NetBIOS resolveOrder specifies WINS however the " +
+                                    "jcifs.netbios.wins property has not been set" );
+                        }
+                        continue;
+                    }
+                    tmp[i++] = RESOLVER_WINS;
+                } else if( s.equalsIgnoreCase( "BCAST" )) {
+                    tmp[i++] = RESOLVER_BCAST;
+                } else if( s.equalsIgnoreCase( "DNS" )) {
+                    ; // skip
+                } else if( log.level > 1 ) {
+                    log.println( "unknown resolver method: " + s );
+                }
+            }
+            resolveOrder = new int[i];
+            System.arraycopy( tmp, 0, resolveOrder, 0, i );
+        }
+    }
+
+    int getNextNameTrnId() {
+        if(( ++nextNameTrnId & 0xFFFF ) == 0 ) {
+            nextNameTrnId = 1;
+        }
+        return nextNameTrnId;
+    }
+    void ensureOpen( int timeout ) throws IOException {
+        closeTimeout = 0;
+        if( SO_TIMEOUT != 0 ) {
+            closeTimeout = Math.max( SO_TIMEOUT, timeout );
+        }
+        // If socket is still good, the new closeTimeout will
+        // be ignored; see tryClose comment.
+        if( socket == null ) {
+            socket = new DatagramSocket( lport, laddr );
+            thread = new Thread( this, "JCIFS-NameServiceClient" );
+            thread.setDaemon( true );
+            thread.start();
+        }
+    }
+    void tryClose() {
+        synchronized( LOCK ) {
+
+            /* Yes, there is the potential to drop packets
+             * because we might close the socket during a
+             * request. However the chances are slim and the
+             * retry code should ensure the overall request
+             * is serviced. The alternative complicates things
+             * more than I think is worth it.
+             */
+
+            if( socket != null ) {
+                socket.close();
+                socket = null;
+            }
+            thread = null;
+            responseTable.clear();
+        }
+    }
+    public void run() {
+        int nameTrnId;
+        NameServicePacket response;
+
+        try {
+            while( thread == Thread.currentThread() ) {
+                in.setLength( RCV_BUF_SIZE );
+
+                socket.setSoTimeout( closeTimeout );
+                socket.receive( in );
+
+                if( log.level > 3 )
+                    log.println( "NetBIOS: new data read from socket" );
+
+                nameTrnId = NameServicePacket.readNameTrnId( rcv_buf, 0 );
+                response = (NameServicePacket)responseTable.get( new Integer( nameTrnId ));
+                if( response == null || response.received ) {
+                    continue;
+                }
+                synchronized( response ) {
+                    response.readWireFormat( rcv_buf, 0 );
+                    response.received = true;
+
+                    if( log.level > 3 ) {
+                        log.println( response );
+                        Hexdump.hexdump( log, rcv_buf, 0, in.getLength() );
+                    }
+
+                    response.notify();
+                }
+            }
+        } catch(SocketTimeoutException ste) {
+        } catch( Exception ex ) {
+            if( log.level > 2 )
+                ex.printStackTrace( log );
+        } finally {
+            tryClose();
+        }
+    }
+    void send( NameServicePacket request, NameServicePacket response,
+                                            int timeout ) throws IOException {
+        Integer nid = null;
+        int max = NbtAddress.NBNS.length;
+
+        if (max == 0)
+            max = 1; /* No WINs, try only bcast addr */
+
+        synchronized( response ) {
+            while (max-- > 0) {
+                try {
+                    synchronized( LOCK ) {
+                        request.nameTrnId = getNextNameTrnId();
+                        nid = new Integer( request.nameTrnId );
+
+                        out.setAddress( request.addr );
+                        out.setLength( request.writeWireFormat( snd_buf, 0 ));
+                        response.received = false;
+
+                        responseTable.put( nid, response );
+                        ensureOpen( timeout + 1000 );
+                        socket.send( out );
+
+                        if( log.level > 3 ) {
+                            log.println( request );
+                            Hexdump.hexdump( log, snd_buf, 0, out.getLength() );
+                        }
+                    }
+
+                    response.wait( timeout );
+
+                    if (response.received)
+                        return;
+
+                } catch( InterruptedException ie ) {
+                } finally {
+                    responseTable.remove( nid );
+                }
+
+                if (NbtAddress.isWINS( request.addr ) == false)
+                    break;
+
+                                /* Message was sent to WINS but
+                                 * failed to receive response.
+                                 * Try a different WINS server.
+                                 */
+                if (request.addr == NbtAddress.getWINSAddress())
+                    NbtAddress.switchWINS();
+                request.addr = NbtAddress.getWINSAddress();
+            }
+        }
+    }
+
+    NbtAddress[] getAllByName( Name name, InetAddress addr )
+                                            throws UnknownHostException {
+        int n;
+        NameQueryRequest request = new NameQueryRequest( name );
+        NameQueryResponse response = new NameQueryResponse();
+
+        request.addr = addr != null ? addr : NbtAddress.getWINSAddress();
+        request.isBroadcast = request.addr == null;
+
+        if( request.isBroadcast ) {
+            request.addr = baddr;
+            n = RETRY_COUNT;
+        } else {
+            request.isBroadcast = false;
+            n = 1;
+        }
+
+        do {
+            try {
+                send( request, response, RETRY_TIMEOUT );
+            } catch( IOException ioe ) {
+                if( log.level > 1 )
+                    ioe.printStackTrace( log );
+                throw new UnknownHostException( name.name );
+            }
+
+            if( response.received && response.resultCode == 0 ) {
+                return response.addrEntry;
+            }
+        } while( --n > 0 && request.isBroadcast );
+
+        throw new UnknownHostException( name.name );
+    }
+    NbtAddress getByName( Name name, InetAddress addr )
+                                            throws UnknownHostException {
+        int n;
+        NameQueryRequest request = new NameQueryRequest( name );
+        NameQueryResponse response = new NameQueryResponse();
+
+        if( addr != null ) { /* UniAddress calls always use this
+                              * because it specifies addr
+                              */
+            request.addr = addr; /* if addr ends with 255 flag it bcast */
+            request.isBroadcast = (addr.getAddress()[3] == (byte)0xFF);
+
+            n = RETRY_COUNT;
+            do {
+                try {
+                    send( request, response, RETRY_TIMEOUT );
+                } catch( IOException ioe ) {
+                    if( log.level > 1 )
+                        ioe.printStackTrace( log );
+                    throw new UnknownHostException( name.name );
+                }
+
+                if( response.received && response.resultCode == 0 ) {
+                    int last = response.addrEntry.length - 1;
+                    response.addrEntry[last].hostName.srcHashCode = addr.hashCode();
+                    return response.addrEntry[last];
+                }
+            } while( --n > 0 && request.isBroadcast );
+
+            throw new UnknownHostException( name.name );
+        }
+
+        /* If a target address to query was not specified explicitly
+         * with the addr parameter we fall into this resolveOrder routine.
+         */
+
+        for( int i = 0; i < resolveOrder.length; i++ ) {
+            try {
+                switch( resolveOrder[i] ) {
+                    case RESOLVER_LMHOSTS:
+                        NbtAddress ans = Lmhosts.getByName( name );
+                        if( ans != null ) {
+                            ans.hostName.srcHashCode = 0; // just has to be different
+                                                          // from other methods
+                            return ans;
+                        }
+                        break;
+                    case RESOLVER_WINS:
+                    case RESOLVER_BCAST:
+                        if( resolveOrder[i] == RESOLVER_WINS &&
+                                name.name != NbtAddress.MASTER_BROWSER_NAME &&
+                                name.hexCode != 0x1d ) {
+                            request.addr = NbtAddress.getWINSAddress();
+                            request.isBroadcast = false;
+                        } else {
+                            request.addr = baddr;
+                            request.isBroadcast = true;
+                        }
+
+                        n = RETRY_COUNT;
+                        while( n-- > 0 ) {
+                            try {
+                                send( request, response, RETRY_TIMEOUT );
+                            } catch( IOException ioe ) {
+                                if( log.level > 1 )
+                                    ioe.printStackTrace( log );
+                                throw new UnknownHostException( name.name );
+                            }
+                            if( response.received && response.resultCode == 0 ) {
+
+/* Before we return, in anticipation of this address being cached we must
+ * augment the addresses name's hashCode to distinguish those resolved by
+ * Lmhosts, WINS, or BCAST. Otherwise a failed query from say WINS would
+ * get pulled out of the cache for a BCAST on the same name.
+ */
+                                response.addrEntry[0].hostName.srcHashCode =
+                                                        request.addr.hashCode();
+                                return response.addrEntry[0];
+                            } else if( resolveOrder[i] == RESOLVER_WINS ) {
+                                /* If WINS reports negative, no point in retry
+                                 */
+                                break;
+                            }
+                        }
+                        break;
+                }
+            } catch( IOException ioe ) {
+            }
+        }
+        throw new UnknownHostException( name.name );
+    }
+    NbtAddress[] getNodeStatus( NbtAddress addr ) throws UnknownHostException {
+        int n, srcHashCode;
+        NodeStatusRequest request;
+        NodeStatusResponse response;
+
+        response = new NodeStatusResponse( addr );
+        request = new NodeStatusRequest(
+                            new Name( NbtAddress.ANY_HOSTS_NAME, 0x00, null));
+        request.addr = addr.getInetAddress();
+
+        n = RETRY_COUNT;
+        while( n-- > 0 ) {
+            try {
+                send( request, response, RETRY_TIMEOUT );
+            } catch( IOException ioe ) {
+                if( log.level > 1 )
+                    ioe.printStackTrace( log );
+                throw new UnknownHostException( addr.toString() );
+            }
+            if( response.received && response.resultCode == 0 ) {
+
+        /* For name queries resolved by different sources (e.g. WINS,
+         * BCAST, Node Status) we need to augment the hashcode generated
+         * for the addresses hostname or failed lookups for one type will
+         * be cached and cause other types to fail even though they may
+         * not be the authority for the name. For example, if a WINS lookup
+         * for FOO fails and caches unknownAddress for FOO, a subsequent
+         * lookup for FOO using BCAST should not fail because of that
+         * name cached from WINS.
+         *
+         * So, here we apply the source addresses hashCode to each name to
+         * make them specific to who resolved the name.
+         */
+
+                srcHashCode = request.addr.hashCode();
+                for( int i = 0; i < response.addressArray.length; i++ ) {
+                    response.addressArray[i].hostName.srcHashCode = srcHashCode;
+                }
+                return response.addressArray;
+            }
+        }
+        throw new UnknownHostException( addr.hostName.name );
+    }
+}
index ae4e82f..558a49d 100644 (file)
@@ -186,6 +186,15 @@ public final class NbtAddress {
             try {
                 localInetAddress = InetAddress.getLocalHost();
             } catch( UnknownHostException uhe ) {
+                /* Java cannot determine the localhost. This is basically a config
+                 * issue on the host. There's not much we can do about it. Just
+                 * to suppress NPEs that would result we can create a possibly bogus
+                 * address. Pretty sure the below cannot actually thrown a UHE tho.
+                 */
+                try {
+                    localInetAddress = InetAddress.getByName("127.0.0.1");
+                } catch( UnknownHostException ignored ) {
+                }
             }
         }
 
diff --git a/src/jcifs/smb/.SmbConstants.java.swp b/src/jcifs/smb/.SmbConstants.java.swp
deleted file mode 100644 (file)
index c8e2999..0000000
Binary files a/src/jcifs/smb/.SmbConstants.java.swp and /dev/null differ
index f3c78fe..6735297 100644 (file)
@@ -59,7 +59,7 @@ public interface DosError {
         { 0x08bf0002, 0xC0000193 },
         { 0x08c00002, 0xC0000070 },
         { 0x08c10002, 0xC000006f },
-        { 0x08c20002, 0xC0000071 }
+        { 0x08c20002, 0xC0000071 },
     };
 
     /* These aren't really used by jCIFS -- the map above is used
@@ -104,7 +104,7 @@ public interface DosError {
         "This user account has expired.",
         "The user is not allowed to log on from this workstation.",
         "The user is not allowed to log on at this time.",
-        "The password of this user has expired."
+        "The password of this user has expired.",
     };
 }
 
index 1f89e4b..bb75090 100644 (file)
@@ -23,50 +23,12 @@ import java.net.URLConnection;
 import java.net.URLStreamHandler;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
-
 import java.io.PrintStream;
 
 public class Handler extends URLStreamHandler {
 
     static final URLStreamHandler SMB_HANDLER = new Handler();
 
-    static String unescape( String str ) throws NumberFormatException, UnsupportedEncodingException {
-        char ch;
-        int i, j, state, len;
-        char[] out;
-        byte[] b = new byte[1];
-
-        if( str == null ) {
-            return null;
-        }
-
-        len = str.length();
-        out = new char[len];
-        state = 0;
-        for( i = j = 0; i < len; i++ ) {
-            switch( state ) {
-                case 0:
-                    ch = str.charAt( i );
-                    if( ch == '%' ) {
-                        state = 1;
-                    } else {
-                        out[j++] = ch;
-                    }
-                    break;
-                case 1:
-                    /* Get ASCII hex value and convert to platform dependant
-                     * encoding like EBCDIC perhaps
-                     */
-                    b[0] = (byte)(Integer.parseInt( str.substring( i, i + 2 ), 16 ) & 0xFF);
-                    out[j++] = (new String( b, 0, 1, "ASCII" )).charAt( 0 );
-                    i++;
-                    state = 0;
-            }
-        }
-
-        return new String( out, 0, j );
-    }
-
     protected int getDefaultPort() {
         return SmbConstants.DEFAULT_PORT;
     }
@@ -75,7 +37,7 @@ public class Handler extends URLStreamHandler {
     }
     protected void parseURL( URL u, String spec, int start, int limit ) {
         String host = u.getHost();
-        String userinfo, path, ref;
+        String path, ref;
         int port;
 
         if( spec.equals( "smb://" )) {
@@ -87,13 +49,8 @@ public class Handler extends URLStreamHandler {
             limit += 2;
         }
         super.parseURL( u, spec, start, limit );
-        userinfo = u.getUserInfo();
         path = u.getPath();
         ref = u.getRef();
-        try {
-            userinfo = unescape( userinfo );
-        } catch( UnsupportedEncodingException uee ) {
-        }
         if (ref != null) {
             path += '#' + ref;
         }
@@ -102,7 +59,7 @@ public class Handler extends URLStreamHandler {
             port = getDefaultPort();
         }
         setURL( u, "smb", u.getHost(), port,
-                    u.getAuthority(), userinfo,
+                    u.getAuthority(), u.getUserInfo(),
                     path, u.getQuery(), null );
     }
 }
index 73c26e9..7a9b22c 100644 (file)
@@ -183,6 +183,10 @@ public final class NtlmPasswordAuthentication implements Principal, Serializable
         domain = username = password = null;
 
         if( userInfo != null ) {
+            try {
+                userInfo = unescape( userInfo );
+            } catch( UnsupportedEncodingException uee ) {
+            }
             int i, u, end;
             char c;
 
@@ -437,5 +441,43 @@ public final class NtlmPasswordAuthentication implements Principal, Serializable
     public String toString() {
         return getName();
     }
+
+    static String unescape( String str ) throws NumberFormatException, UnsupportedEncodingException {
+        char ch;
+        int i, j, state, len;
+        char[] out;
+        byte[] b = new byte[1];
+
+        if( str == null ) {
+            return null;
+        }
+
+        len = str.length();
+        out = new char[len];
+        state = 0;
+        for( i = j = 0; i < len; i++ ) {
+            switch( state ) {
+                case 0:
+                    ch = str.charAt( i );
+                    if( ch == '%' ) {
+                        state = 1;
+                    } else {
+                        out[j++] = ch;
+                    }
+                    break;
+                case 1:
+                    /* Get ASCII hex value and convert to platform dependant
+                     * encoding like EBCDIC perhaps
+                     */
+                    b[0] = (byte)(Integer.parseInt( str.substring( i, i + 2 ), 16 ) & 0xFF);
+                    out[j++] = (new String( b, 0, 1, "ASCII" )).charAt( 0 );
+                    i++;
+                    state = 0;
+            }
+        }
+
+        return new String( out, 0, j );
+    }
+
 }
 
diff --git a/src/jcifs/smb/NtlmPasswordAuthentication.java.orig b/src/jcifs/smb/NtlmPasswordAuthentication.java.orig
new file mode 100644 (file)
index 0000000..73c26e9
--- /dev/null
@@ -0,0 +1,441 @@
+/* jcifs smb client library in Java
+ * Copyright (C) 2002  "Michael B. Allen" <jcifs at samba dot org>
+ *                  "Eric Glass" <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.io.UnsupportedEncodingException;
+import java.io.Serializable;
+import java.security.Principal;
+import java.util.Random;
+import java.util.Arrays;
+import jcifs.Config;
+import jcifs.util.*;
+
+/**
+ * This class stores and encrypts NTLM user credentials. The default
+ * credentials are retrieved from the <tt>jcifs.smb.client.domain</tt>,
+ * <tt>jcifs.smb.client.username</tt>, and <tt>jcifs.smb.client.password</tt>
+ * properties.
+ * <p>
+ * Read <a href="../../../authhandler.html">jCIFS Exceptions and
+ * NtlmAuthenticator</a> for related information.
+ */
+
+public final class NtlmPasswordAuthentication implements Principal, Serializable {
+
+    private static final int LM_COMPATIBILITY =
+            Config.getInt("jcifs.smb.lmCompatibility", 0);
+
+    private static final Random RANDOM = new Random();
+
+    private static LogStream log = LogStream.getInstance();
+
+    // KGS!@#$%
+    private static final byte[] S8 = {
+        (byte)0x4b, (byte)0x47, (byte)0x53, (byte)0x21,
+        (byte)0x40, (byte)0x23, (byte)0x24, (byte)0x25
+    };
+    private static void E( byte[] key, byte[] data, byte[] e ) {
+        byte[] key7 = new byte[7];
+        byte[] e8 = new byte[8];
+
+        for( int i = 0; i < key.length / 7; i++ ) {
+            System.arraycopy( key, i * 7, key7, 0, 7 );
+            DES des = new DES( key7 );
+            des.encrypt( data, e8 );
+            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.
+ */
+    static public byte[] getPreNTLMResponse( String password, byte[] challenge ) {
+        byte[] p14 = new byte[14];
+        byte[] p21 = new byte[21];
+        byte[] p24 = new byte[24];
+        byte[] passwordBytes;
+        try {
+            passwordBytes = password.toUpperCase().getBytes( ServerMessageBlock.OEM_ENCODING );
+        } catch( UnsupportedEncodingException uee ) {
+            throw new RuntimeException("Try setting jcifs.encoding=US-ASCII", uee);
+        }
+        int passwordLength = passwordBytes.length;
+
+        // Only encrypt the first 14 bytes of the password for Pre 0.12 NT LM
+        if( passwordLength > 14) {
+            passwordLength = 14;
+        }
+        System.arraycopy( passwordBytes, 0, p14, 0, passwordLength );
+        E( p14, S8, p21);
+        E( p21, challenge, p24);
+        return p24;
+    }
+/**
+ * Generate the Unicode MD4 hash for the password associated with these credentials.
+ */
+    static public byte[] getNTLMResponse( String password, byte[] challenge ) {
+        byte[] uni = null;
+        byte[] p21 = new byte[21];
+        byte[] p24 = new byte[24];
+
+        try {
+            uni = password.getBytes( "UnicodeLittleUnmarked" );
+        } catch( UnsupportedEncodingException uee ) {
+            if( log.level > 0 )
+                uee.printStackTrace( log );
+        }
+        MD4 md4 = new MD4();
+        md4.update( uni );
+        try {
+            md4.digest(p21, 0, 16);
+        } catch (Exception ex) {
+            if( log.level > 0 )
+                ex.printStackTrace( log );
+        }
+        E( p21, challenge, p24 );
+        return p24;
+    }
+
+    /**
+     * Creates the LMv2 response for the supplied information.
+     *
+     * @param domain The domain in which the username exists.
+     * @param user The username.
+     * @param password The user's password.
+     * @param challenge The server challenge.
+     * @param clientChallenge The client challenge (nonce). 
+     */ 
+    public static byte[] getLMv2Response(String domain, String user,
+            String password, byte[] challenge, byte[] clientChallenge) {
+        try {
+            byte[] hash = new byte[16];
+            byte[] response = new byte[24];
+            MD4 md4 = new MD4();
+            md4.update(password.getBytes("UnicodeLittleUnmarked"));
+            HMACT64 hmac = new HMACT64(md4.digest());
+            hmac.update(user.toUpperCase().getBytes("UnicodeLittleUnmarked"));
+            hmac.update(domain.toUpperCase().getBytes("UnicodeLittleUnmarked"));
+            hmac = new HMACT64(hmac.digest());
+            hmac.update(challenge);
+            hmac.update(clientChallenge);
+            hmac.digest(response, 0, 16);
+            System.arraycopy(clientChallenge, 0, response, 16, 8);
+            return response;
+        } catch (Exception ex) {
+            if( log.level > 0 )
+                ex.printStackTrace( log );
+            return null;
+        }
+    }
+
+    static final NtlmPasswordAuthentication NULL =
+                new NtlmPasswordAuthentication( "", "", "" );
+    static final NtlmPasswordAuthentication GUEST =
+                new NtlmPasswordAuthentication( "?", "GUEST", "" );
+    static final NtlmPasswordAuthentication DEFAULT =
+                new NtlmPasswordAuthentication( null );
+
+    String domain;
+    String username;
+    String password;
+    byte[] ansiHash;
+    byte[] unicodeHash;
+    boolean hashesExternal = false;
+    byte[] clientChallenge = null;
+    byte[] challenge = null;
+
+/**
+ * Create an <tt>NtlmPasswordAuthentication</tt> object from the userinfo
+ * component of an SMB URL like "<tt>domain;user:pass</tt>". This constructor
+ * is used internally be jCIFS when parsing SMB URLs.
+ */
+
+    public NtlmPasswordAuthentication( String userInfo ) {
+        domain = username = password = null;
+
+        if( userInfo != null ) {
+            int i, u, end;
+            char c;
+
+            end = userInfo.length();
+            for( i = 0, u = 0; i < end; i++ ) {
+                c = userInfo.charAt( i );
+                if( c == ';' ) {
+                    domain = userInfo.substring( 0, i );
+                    u = i + 1;
+                } else if( c == ':' ) {
+                    password = userInfo.substring( i + 1 );
+                    break;
+                }
+            }
+            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;
+    }
+/**
+ * Create an <tt>NtlmPasswordAuthentication</tt> object from a
+ * domain, username, and password. Parameters that are <tt>null</tt>
+ * will be substituted with <tt>jcifs.smb.client.domain</tt>,
+ * <tt>jcifs.smb.client.username</tt>, <tt>jcifs.smb.client.password</tt>
+ * property values.
+ */
+    public NtlmPasswordAuthentication( String domain, String username, String 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;
+    }
+/**
+ * Create an <tt>NtlmPasswordAuthentication</tt> object with raw password
+ * hashes. This is used exclusively by the <tt>jcifs.http.NtlmSsp</tt>
+ * class which is in turn used by NTLM HTTP authentication functionality.
+ */
+    public NtlmPasswordAuthentication( String domain, String username,
+                    byte[] challenge, byte[] ansiHash, byte[] unicodeHash ) {
+        if( domain == null || username == null ||
+                                    ansiHash == null || unicodeHash == null ) {
+            throw new IllegalArgumentException( "External credentials cannot be null" );
+        }
+        this.domain = domain;
+        this.username = username;
+        this.password = null;
+        this.challenge = challenge;
+        this.ansiHash = ansiHash;
+        this.unicodeHash = unicodeHash;
+        hashesExternal = true;
+    }
+
+/**
+ * Returns the domain.
+ */
+    public String getDomain() {
+        return domain;
+    }
+/**
+ * Returns the username.
+ */
+    public String getUsername() {
+        return username;
+    }
+/**
+ * Returns the password in plain text or <tt>null</tt> if the raw password
+ * hashes were used to construct this <tt>NtlmPasswordAuthentication</tt>
+ * object which will be the case when NTLM HTTP Authentication is
+ * used. There is no way to retrieve a users password in plain text unless
+ * it is supplied by the user at runtime.
+ */
+    public String getPassword() {
+        return password;
+    }
+/**
+ * Return the domain and username in the format:
+ * <tt>domain\\username</tt>. This is equivalent to <tt>toString()</tt>.
+ */
+    public String getName() {
+        boolean d = domain.length() > 0 && domain.equals( "?" ) == false;
+        return d ? domain + "\\" + username : username;
+    }
+
+/**
+ * Computes the 24 byte ANSI password hash given the 8 byte server challenge.
+ */
+    public byte[] getAnsiHash( byte[] challenge ) {
+        if( hashesExternal ) {
+            return ansiHash;
+        }
+        switch (LM_COMPATIBILITY) {
+        case 0:
+        case 1:
+            return getPreNTLMResponse( password, challenge );
+        case 2:
+            return getNTLMResponse( password, challenge );
+        case 3:
+        case 4:
+        case 5:
+            if( clientChallenge == null ) {
+                clientChallenge = new byte[8];
+                RANDOM.nextBytes( clientChallenge );
+            }
+            return getLMv2Response(domain, username, password, challenge,
+                    clientChallenge);
+        default:
+            return getPreNTLMResponse( password, challenge );
+        }
+    }
+/**
+ * Computes the 24 byte Unicode password hash given the 8 byte server challenge.
+ */
+    public byte[] getUnicodeHash( byte[] challenge ) {
+        if( hashesExternal ) {
+            return unicodeHash;
+        }
+        switch (LM_COMPATIBILITY) {
+        case 0:
+        case 1:
+        case 2:
+            return getNTLMResponse( password, challenge );
+        case 3:
+        case 4:
+        case 5:
+            /*
+            if( clientChallenge == null ) {
+                clientChallenge = new byte[8];
+                RANDOM.nextBytes( clientChallenge );
+            }
+            return getNTLMv2Response(domain, username, password, null,
+                    challenge, clientChallenge);
+            */
+            return new byte[0];
+        default:
+            return getNTLMResponse( password, challenge );
+        }
+    }
+
+    /**
+     * Returns the effective user session key.
+     * 
+     * @param challenge The server challenge.
+     * @return A <code>byte[]</code> containing the effective user session key,
+     * used in SMB MAC signing and NTLMSSP signing and sealing.
+     */
+    public byte[] getUserSessionKey(byte[] challenge) {
+        if (hashesExternal) return null;
+        byte[] key = new byte[16];
+        try {
+            getUserSessionKey(challenge, key, 0); 
+        } catch (Exception ex) {
+            if( log.level > 0 )
+                ex.printStackTrace( log );
+        }
+        return key; 
+    }
+
+    /**
+     * Calculates the effective user session key.
+     *
+     * @param challenge The server challenge.
+     * @param dest The destination array in which the user session key will be
+     * placed.
+     * @param offset The offset in the destination array at which the
+     * session key will start.
+     */
+    void getUserSessionKey(byte[] challenge, byte[] dest, int offset)
+            throws Exception {
+        if (hashesExternal) return;
+        MD4 md4 = new MD4();
+        md4.update(password.getBytes("UnicodeLittleUnmarked")); 
+        switch (LM_COMPATIBILITY) {
+        case 0:
+        case 1:
+        case 2:
+            md4.update(md4.digest()); 
+            md4.digest(dest, offset, 16); 
+            break; 
+        case 3:
+        case 4:
+        case 5:
+            if( clientChallenge == null ) {
+                clientChallenge = new byte[8];
+                RANDOM.nextBytes( clientChallenge );
+            }
+
+            HMACT64 hmac = new HMACT64(md4.digest());
+            hmac.update(username.toUpperCase().getBytes(
+                    "UnicodeLittleUnmarked"));
+            hmac.update(domain.toUpperCase().getBytes(
+                    "UnicodeLittleUnmarked"));
+            byte[] ntlmv2Hash = hmac.digest();
+            hmac = new HMACT64(ntlmv2Hash);
+            hmac.update(challenge);
+            hmac.update(clientChallenge); 
+            HMACT64 userKey = new HMACT64(ntlmv2Hash); 
+            userKey.update(hmac.digest()); 
+            userKey.digest(dest, offset, 16); 
+            break; 
+        default: 
+            md4.update(md4.digest()); 
+            md4.digest(dest, offset, 16); 
+            break; 
+        } 
+    } 
+
+/**
+ * Compares two <tt>NtlmPasswordAuthentication</tt> objects for
+ * equality. Two <tt>NtlmPasswordAuthentication</tt> objects are equal if
+ * their caseless domain and username fields are equal and either both hashes are external and they are equal or both internally supplied passwords are equal. If one <tt>NtlmPasswordAuthentication</tt> object has external hashes (meaning negotiated via NTLM HTTP Authentication) and the other does not they will not be equal. This is technically not correct however the server 8 byte challage would be required to compute and compare the password hashes but that it not available with this method.
+ */
+    public boolean equals( Object obj ) {
+        if( obj instanceof NtlmPasswordAuthentication ) {
+            NtlmPasswordAuthentication ntlm = (NtlmPasswordAuthentication)obj;
+            if( ntlm.domain.toUpperCase().equals( domain.toUpperCase() ) &&
+                        ntlm.username.toUpperCase().equals( username.toUpperCase() )) {
+                if( hashesExternal && ntlm.hashesExternal ) {
+                    return Arrays.equals( ansiHash, ntlm.ansiHash ) &&
+                                Arrays.equals( unicodeHash, ntlm.unicodeHash );
+                    /* This still isn't quite right. If one npa object does not have external
+                     * hashes and the other does then they will not be considered equal even
+                     * though they may be.
+                     */
+                } else if( !hashesExternal && password.equals( ntlm.password )) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+
+/**
+ * Return the upcased username hash code.
+ */
+    public int hashCode() {
+        return getName().toUpperCase().hashCode();
+    }
+/**
+ * Return the domain and username in the format:
+ * <tt>domain\\username</tt>. This is equivalent to <tt>getName()</tt>.
+ */
+    public String toString() {
+        return getName();
+    }
+}
+
index 5b98f31..8be869c 100644 (file)
@@ -187,13 +187,14 @@ public class SID extends rpc.sid_t {
         DcerpcHandle handle = null;
         LsaPolicyHandle policyHandle = null;
         lsarpc.LsarDomainInfo info = new lsarpc.LsarDomainInfo();
-        MsrpcQueryInformationPolicy2 rpc;
+        MsrpcQueryInformationPolicy rpc;
 
         try {
             handle = DcerpcHandle.getHandle("ncacn_np:" + server +
                     "[\\PIPE\\lsarpc]", auth);
-            policyHandle = new LsaPolicyHandle(handle, null, 0x02000000);
-            rpc = new MsrpcQueryInformationPolicy2(policyHandle,
+            // NetApp doesn't like the 'generic' access mask values
+            policyHandle = new LsaPolicyHandle(handle, null, 0x00000001);
+            rpc = new MsrpcQueryInformationPolicy(policyHandle,
                         (short)lsarpc.POLICY_INFO_ACCOUNT_DOMAIN,
                         info);
             handle.sendrecv(rpc);
index 2c7c7bc..ae32161 100644 (file)
@@ -11,9 +11,7 @@ import jcifs.util.Hexdump;
  * To filter 0 len updates and for debugging
  */
 
-public class SigningDigest {
-
-    private static final int LM_COMPATIBILITY = Config.getInt( "jcifs.smb.lmCompatibility", 0);
+public class SigningDigest implements SmbConstants {
 
     static LogStream log = LogStream.getInstance();
 
index 125511b..99b3b51 100644 (file)
@@ -18,6 +18,7 @@
 
 package jcifs.smb;
 
+import java.util.Arrays;
 import jcifs.Config;
 
 class SmbComSessionSetupAndX extends AndXServerMessageBlock {
@@ -40,7 +41,8 @@ class SmbComSessionSetupAndX extends AndXServerMessageBlock {
         command = SMB_COM_SESSION_SETUP_ANDX;
         this.session = session;
         this.auth = session.auth;
-        if( auth.hashesExternal && auth.challenge != session.transport.server.encryptionKey ) {
+        if( auth.hashesExternal &&
+                    Arrays.equals(auth.challenge, session.transport.server.encryptionKey) == false ) {
             throw new SmbAuthException( SmbException.NT_STATUS_ACCESS_VIOLATION );
         }
     }
index 80a816e..439b634 100644 (file)
@@ -29,6 +29,7 @@ interface SmbConstants {
     static final boolean USE_EXTSEC = Config.getBoolean( "jcifs.smb.client.useExtendedSecurity", false );
 
     static final String NETBIOS_HOSTNAME = Config.getProperty( "jcifs.netbios.hostname", null );
+    static final int LM_COMPATIBILITY = Config.getInt( "jcifs.smb.lmCompatibility", 0);
 
     static final int FLAGS_NONE                           = 0x00;
     static final int FLAGS_LOCK_AND_READ_WRITE_AND_UNLOCK = 0x01;
index 090f193..08c140c 100644 (file)
@@ -42,11 +42,17 @@ public class SmbException extends IOException implements NtStatus, DosError, Win
     static String getMessageByCode( int errcode ) {
         if(( errcode & 0xC0000000 ) == 0xC0000000 ) {
             int min = 0;
-            int max = NT_STATUS_CODES.length;
+            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] ) {
@@ -57,7 +63,7 @@ public class SmbException extends IOException implements NtStatus, DosError, Win
             }
         } else {
             int min = 0;
-            int max = DOS_ERROR_CODES.length;
+            int max = DOS_ERROR_CODES.length - 1;
 
             while( max >= min ) {
                 int mid = (min + max) / 2;
@@ -79,7 +85,7 @@ public class SmbException extends IOException implements NtStatus, DosError, Win
             return errcode;
         } else {
             int min = 0;
-            int max = DOS_ERROR_CODES.length;
+            int max = DOS_ERROR_CODES.length - 1;
 
             while( max >= min ) {
                 int mid = (min + max) / 2;
@@ -98,7 +104,7 @@ public class SmbException extends IOException implements NtStatus, DosError, Win
     }
     static String getMessageByWinerrCode( int errcode ) {
         int min = 0;
-        int max = WINERR_CODES.length;
+        int max = WINERR_CODES.length - 1;
 
         while( max >= min ) {
             int mid = (min + max) / 2;
index 1dca19a..71f1399 100644 (file)
@@ -94,8 +94,8 @@ int retry = 1;
 
 do {
             if (dc_list_expiration < now) {
-                dc_list_expiration = now + CACHE_POLICY * 1000L;
                 NbtAddress[] list = NbtAddress.getAllByName( DOMAIN, 0x1C, null, null );
+                dc_list_expiration = now + CACHE_POLICY * 1000L;
                 if (list != null && list.length > 0) {
                     dc_list = list;
                 } else { /* keep using the old list */
@@ -239,9 +239,10 @@ do {
             transport.send( request, response );
         }
     }
-int x = 0;
     void sessionSetup( ServerMessageBlock andx,
                             ServerMessageBlock andxResponse ) throws SmbException {
+        SmbException ex = null;
+
 synchronized( transport() ) {
         if( sessionSetup ) {
             return;
@@ -274,7 +275,14 @@ synchronized( transport() ) {
         }
 
         request.auth = auth;
-        transport.send( request, response );
+
+        try {
+            transport.send( request, response );
+        } catch (SmbAuthException sae) {
+            throw sae;
+        } catch (SmbException se) {
+            ex = se;
+        }
 
         if( response.isLoggedInAsGuest &&
                     "GUEST".equalsIgnoreCase( auth.username ) == false) {
@@ -288,6 +296,9 @@ synchronized( transport() ) {
             /* success - install the signing digest */
             transport.digest = request.digest;
         }
+
+        if (ex != null)
+            throw ex;
 }
     }
     void logoff( boolean inError ) {
diff --git a/src/jcifs/smb/SmbSession.java.orig b/src/jcifs/smb/SmbSession.java.orig
new file mode 100644 (file)
index 0000000..1dca19a
--- /dev/null
@@ -0,0 +1,327 @@
+/* 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 + "]";
+    }
+}
index 208b941..32ad4da 100644 (file)
@@ -160,7 +160,7 @@ public class SmbTransport extends Transport implements SmbConstants {
         try {
             connect( RESPONSE_TIMEOUT );
         } catch( IOException ioe ) {
-            throw new SmbException( "", ioe );
+            throw new SmbException( ioe.getMessage(), ioe );
         }
         return (capabilities & cap) == cap;
     }
@@ -286,7 +286,7 @@ public class SmbTransport extends Transport implements SmbConstants {
         try {
             super.connect( RESPONSE_TIMEOUT );
         } catch( TransportException te ) {
-            throw new SmbException( "", te );
+            throw new SmbException( te.getMessage(), te );
         }
     }
     protected void doConnect() throws IOException {
@@ -308,6 +308,9 @@ public class SmbTransport extends Transport implements SmbConstants {
         if( resp.dialectIndex > 10 ) {
             throw new SmbException( "This client does not support the negotiated dialect." );
         }
+        if (server.encryptionKeyLength != 8 && LM_COMPATIBILITY == 0) {
+            throw new SmbException("Encryption key length is not 8 as expected. This could indicate that the server requires NTLMv2. JCIFS does not fully support NTLMv2 but you can try setting jcifs.smb.lmCompatibility = 3.");
+        }
 
         /* Adjust negotiated values */
 
@@ -442,7 +445,8 @@ public class SmbTransport extends Transport implements SmbConstants {
             if (size < (HEADER_LENGTH + 1) || (4 + size) > rcv_buf_size ) {
                 throw new IOException( "Invalid payload size: " + size );
             }
-            if (resp.command == ServerMessageBlock.SMB_COM_READ_ANDX) {
+            int errorCode = Encdec.dec_uint32le( BUF, 9 ) & 0xFFFFFFFF;
+            if (resp.command == ServerMessageBlock.SMB_COM_READ_ANDX && errorCode == 0) {
                 SmbComReadAndXResponse r = (SmbComReadAndXResponse)resp;
                 int off = HEADER_LENGTH;
                                     /* WordCount thru dataOffset always 27 */
@@ -608,7 +612,7 @@ public class SmbTransport extends Transport implements SmbConstants {
         } catch( SmbException se ) {
             throw se;
         } catch( IOException ioe ) {
-            throw new SmbException( "", ioe );
+            throw new SmbException( ioe.getMessage(), ioe );
         }
 
         checkStatus( request, response );
index 934549b..e244384 100644 (file)
@@ -193,7 +193,7 @@ public abstract class Transport implements Runnable {
         } finally {
             /* This guarantees that we leave in a valid state
              */
-            if (state != 0 && state != 3) {
+            if (state != 0 && state != 3 && state != 4) {
                 if (log.level >= 1)
                     log.println("Invalid state: " + state);
                 state = 0;