jcifs-0.7.13 from tgz
authorFelix Schumacher <p0354740@isib001.(none)>
Wed, 6 Aug 2008 14:08:02 +0000 (16:08 +0200)
committerFelix Schumacher <p0354740@isib001.(none)>
Wed, 6 Aug 2008 14:08:02 +0000 (16:08 +0200)
Wed Sep 17 21:21:31 EDT 2003

SMB  signing  is  now  supported  and  there  have been some adjustments to
SmbFile.hashCode() and SmbFile.equals()

Mon Sep  1 19:18:52 EDT 2003

Added   code  to  logoff  1/10th  of  all  sessions  over  a  transport  if
jcifs.smb.client.ssnLimit is reached (fix for ERRSVR/90 errors).

23 files changed:
CHANGES.txt
README.txt
build.xml
examples/Equals.java [new file with mode: 0644]
src/jcifs/smb/NtlmPasswordAuthentication.java
src/jcifs/smb/ServerMessageBlock.java
src/jcifs/smb/SmbComSessionSetupAndX.java0 [deleted file]
src/jcifs/smb/SmbException.java
src/jcifs/smb/SmbFile.java
src/jcifs/smb/SmbSession.java
src/jcifs/smb/SmbTransport.java
src/jcifs/smb/SmbTransport.java.bak [new file with mode: 0644]
update/Base64.java [deleted file]
update/HMACT64.java [deleted file]
update/NtlmHttpFilter.java [deleted file]
update/NtlmHttpURLConnection.java [deleted file]
update/NtlmMessage.java [deleted file]
update/NtlmPasswordAuthentication.java [deleted file]
update/NtlmServlet.java [deleted file]
update/NtlmSsp.java [deleted file]
update/Type1Message.java [deleted file]
update/Type2Message.java [deleted file]
update/Type3Message.java [deleted file]

index 2b77d33..def84bd 100644 (file)
@@ -1,3 +1,24 @@
+Wed Sep 17 21:21:31 EDT 2003
+
+JCIFS  now  supports SMB signing. If a server requires SMB signing (Windows
+2003  requires  it  by  default)  or if the server supports signing and the
+jcifs.smb.client.signingPreferred   property   is   true  signing  will  be
+negotiated  and  used.  Signing does not work with NTLM HTTP authentication
+because  the  original  password  hashes  are  required to generate the MAC
+signing  key.  There  have  also been some adjustments to SmbFile.hashCode.
+Previously  jCIFS  did  not precisely exhibit the behavior described in the
+comments for hashCode() and equals(). 
+
+Mon Sep  1 19:04:11 EDT 2003
+
+CIFS  permits  multiple  users  to  be  logged  in  over the same transport
+(socket).  JCIFS  takes  advantage  of  this and reuses existing transports
+whenever  possible.  It  was  reported  that  a user using the NTLM Servlet
+Filter  was  getting  ERRSRV/90  which  means "Too many Uids active on this
+session". So it looks like the limit is ~150 sessions per transport. I have
+added    code    to    logoff    1/10th    of    the    sessions   if   the
+jcifs.smb.client.ssnLimit propery is exceeded (default 100). 
+
 Thu Jul 10 22:07:09 EDT 2003
 
 Support  for  LMv2  authentication has been added. See the Overview page in
index b16e455..05acc07 100644 (file)
@@ -1,3 +1,13 @@
+Wed Sep 17 21:21:31 EDT 2003
+
+SMB  signing  is  now  supported  and  there  have been some adjustments to
+SmbFile.hashCode() and SmbFile.equals() 
+
+Mon Sep  1 19:18:52 EDT 2003
+
+Added   code  to  logoff  1/10th  of  all  sessions  over  a  transport  if
+jcifs.smb.client.ssnLimit is reached (fix for ERRSVR/90 errors).
+
 Thu Jul 10 22:07:09 EDT 2003
 
 Support  for  LMv2  authentication has been added.
index b7a2669..f7caea3 100644 (file)
--- a/build.xml
+++ b/build.xml
        <target name="jar" depends="smb">
                <copy file="src/jcifs/util/mime.map" tofile="build/jcifs/util/mime.map" overwrite="yes"/>
                <copy file="src/jcifs/http/ne.css" tofile="build/jcifs/http/ne.css" overwrite="yes"/>
-               <jar jarfile="jcifs-0.7.11.jar" basedir="build"/>
+               <jar jarfile="jcifs-0.7.13.jar" basedir="build"/>
        </target>
 
        <target name="tgz">
-               <copy todir="dist_tmp/jcifs_0.7.11">
+               <copy todir="dist_tmp/jcifs_0.7.13">
                        <fileset dir="." excludes="ant,**/.*,build,jcifs.prp,**/*.tgz,**/*.zip"/>
                </copy>
-               <tar tarfile="jcifs-0.7.11.tar" basedir="dist_tmp"/>
-               <gzip src="jcifs-0.7.11.tar" zipfile="jcifs-0.7.11.tgz"/>
-               <delete file="jcifs-0.7.11.tar"/>
+               <tar tarfile="jcifs-0.7.13.tar" basedir="dist_tmp"/>
+               <gzip src="jcifs-0.7.13.tar" zipfile="jcifs-0.7.13.tgz"/>
+               <delete file="jcifs-0.7.13.tar"/>
                <delete dir="dist_tmp"/>
        </target>
        <target name="zip">
-               <copy todir="dist_tmp/jcifs_0.7.11">
+               <copy todir="dist_tmp/jcifs_0.7.13">
                        <fileset dir="." excludes="ant,**/.*,build,jcifs.prp,**/*.tgz,**/*.zip"/>
                </copy>
                <fixcrlf srcdir="dist_tmp" cr="add" tab="remove" tablength="4" excludes="**/*.jar,**/*.exe"/>
-               <zip zipfile="jcifs-0.7.11.zip" basedir="dist_tmp"/>
+               <zip zipfile="jcifs-0.7.13.zip" basedir="dist_tmp"/>
                <delete dir="dist_tmp"/>
        </target>
 
diff --git a/examples/Equals.java b/examples/Equals.java
new file mode 100644 (file)
index 0000000..6fbe616
--- /dev/null
@@ -0,0 +1,12 @@
+import jcifs.smb.SmbFile;
+
+public class Equals {
+
+       public static void main( String argv[] ) throws Exception {
+
+               SmbFile f1 = new SmbFile( argv[0] );
+               SmbFile f2 = new SmbFile( argv[1] );
+               System.err.println( f1.equals( f2 ));
+       }
+}
+
index c076ab8..d5650de 100644 (file)
@@ -24,7 +24,7 @@ import jcifs.util.MD4;
 import jcifs.util.HMACT64;
 import java.io.UnsupportedEncodingException;
 import java.security.Principal;
-import java.security.SecureRandom;
+import java.util.Random;
 import java.util.Arrays;
 import jcifs.Config;
 
@@ -52,7 +52,7 @@ public final class NtlmPasswordAuthentication implements Principal {
        private static final String DEFAULT_PASSWORD =
                        Config.getProperty("jcifs.smb.client.password", "");
 
-       private static final SecureRandom random = new SecureRandom();
+       private static final Random RANDOM = new Random();
 
        // KGS!@#$%
        static final byte[] S8 = {
@@ -160,6 +160,7 @@ public final class NtlmPasswordAuthentication implements Principal {
        byte[] ansiHash;
        byte[] unicodeHash;
        boolean hashesExternal = false;
+    byte[] clientChallenge = null;
 
 /**
  * Create an <tt>NtlmPasswordAuthentication</tt> object from the userinfo
@@ -256,6 +257,7 @@ public final class NtlmPasswordAuthentication implements Principal {
                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.
  */
@@ -272,8 +274,10 @@ public final class NtlmPasswordAuthentication implements Principal {
                case 3:
                case 4:
                case 5:
-                       byte[] clientChallenge = new byte[8];
-                       random.nextBytes(clientChallenge);
+                       if( clientChallenge == null ) {
+                               clientChallenge = new byte[8];
+                               RANDOM.nextBytes( clientChallenge );
+                       }
                        return getLMv2Response(domain, username, password, challenge,
                                        clientChallenge);
                default:
@@ -296,8 +300,10 @@ public final class NtlmPasswordAuthentication implements Principal {
                case 4:
                case 5:
                        /*
-                       byte[] clientChallenge = new byte[8];
-                       random.nextBytes(clientChallenge);
+                       if( clientChallenge == null ) {
+                               clientChallenge = new byte[8];
+                               RANDOM.nextBytes( clientChallenge );
+                       }
                        return getNTLMv2Response(domain, username, password, null,
                                        challenge, clientChallenge);
                        */
@@ -306,6 +312,74 @@ public final class NtlmPasswordAuthentication implements Principal {
                        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) {
+            Log.printStackTrace("Unable to calculate user session key.", ex);
+        }
+        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
index 7d5f6e4..f216d5d 100644 (file)
@@ -94,6 +94,7 @@ abstract class ServerMessageBlock {
        static final int CMD_OFFSET        = 4;
        static final int ERROR_CODE_OFFSET = 5;
        static final int FLAGS_OFFSET      = 9;
+       static final int SIGNATURE_OFFSET  = 14;
        static final int TID_OFFSET        = 24;
        static final int HEADER_LENGTH     = 32;
 
@@ -261,6 +262,7 @@ abstract class ServerMessageBlock {
                wordCount, byteCount;
        boolean useUnicode, received;
        long responseTimeout = 1;
+       int verifySequence;
 
        ServerMessageBlock() {
                flags = (byte)( FLAGS_PATH_NAMES_CASELESS | FLAGS_PATH_NAMES_CANONICALIZED );
diff --git a/src/jcifs/smb/SmbComSessionSetupAndX.java0 b/src/jcifs/smb/SmbComSessionSetupAndX.java0
deleted file mode 100644 (file)
index da61a71..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/* 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 jcifs.Config;
-import java.io.IOException;
-import java.io.InputStream;
-
-class SmbComSessionSetupAndX extends AndXServerMessageBlock {
-
-       static final int BATCH_LIMIT =
-                       Config.getInt( "jcifs.smb.client.SessionSetupAndX.TreeConnectAndX", 1 );
-
-       byte[] accountPassword, unicodePassword;
-       int passwordLength, unicodePasswordLength;
-       int negotiatedMaxBufferSize,
-               negotiatedMaxMpxCount,
-               vcNumber,
-               sessionKey;
-       String accountName,
-               primaryDomain,
-               nativeOs,
-               nativeLanMan;
-
-       SmbSession session;
-
-       SmbComSessionSetupAndX( SmbSession session, ServerMessageBlock andx ) {
-               super( andx );
-               command = SMB_COM_SESSION_SETUP_ANDX;
-               this.session = session;
-       }
-
-       int getBatchLimit( byte command ) {
-               return command == SMB_COM_TREE_CONNECT_ANDX ? BATCH_LIMIT : 0;
-       }
-       int writeParameterWordsWireFormat( byte[] dst, int dstIndex ) {
-               int start = dstIndex;
-
-               if( session.transport.server.security == SECURITY_USER &&
-                                               ( session.auth.hashesExternal ||
-                                               session.auth.password.length() > 0 )) {
-                       if( session.transport.server.encryptedPasswords ) {
-                               // encrypted
-                               accountPassword = session.auth.getAnsiHash( session.transport.server.encryptionKey );
-                               unicodePassword = session.auth.getUnicodeHash( session.transport.server.encryptionKey );
-                               // fix for NTLMv2 or empty NTLM/LM
-                               passwordLength = accountPassword.length;
-                               unicodePasswordLength = unicodePassword.length;
-                       } else if( Config.getBoolean( "jcifs.smb.client.disablePlainTextPasswords", true )) {
-                               throw new RuntimeException( "Plain text passwords are disabled" );
-                       } else if( useUnicode ) {
-                               // plain text
-                               String password = session.auth.getPassword();
-                               accountPassword = new byte[0];
-                               passwordLength = 0;
-                               unicodePassword = new byte[(password.length() + 1) * 2];
-                               unicodePasswordLength = writeString( password, unicodePassword, 0 );
-                       } else {
-                               // plain text
-                               String password = session.auth.getPassword();
-                               accountPassword = new byte[(password.length() + 1) * 2];
-                               passwordLength = writeString( password, accountPassword, 0 );
-                               unicodePassword = new byte[0];
-                               unicodePasswordLength = 0;
-                       }
-               } else {
-                       // no password in session setup
-                       passwordLength = unicodePasswordLength = 0;
-               }
-
-               negotiatedMaxBufferSize = session.transport.negotiatedMaxBufferSize;
-               negotiatedMaxMpxCount = session.transport.negotiatedMaxMpxCount;
-               vcNumber = session.transport.client.vcNumber;
-               sessionKey = session.transport.client.sessionKey;
-
-               writeInt2( negotiatedMaxBufferSize, dst, dstIndex );
-               dstIndex += 2;
-               writeInt2( negotiatedMaxMpxCount, dst, dstIndex );
-               dstIndex += 2;
-               writeInt2( vcNumber, dst, dstIndex );
-               dstIndex += 2;
-               writeInt4( sessionKey, dst, dstIndex );
-               dstIndex += 4;
-               writeInt2( passwordLength, dst, dstIndex );
-               dstIndex += 2;
-               writeInt2( unicodePasswordLength, dst, dstIndex );
-               dstIndex += 2;
-               dst[dstIndex++] = (byte)0x00;
-               dst[dstIndex++] = (byte)0x00;
-               dst[dstIndex++] = (byte)0x00;
-               dst[dstIndex++] = (byte)0x00;
-               writeInt4( session.transport.client.capabilities, dst, dstIndex );
-               dstIndex += 4;
-
-               return dstIndex - start;
-       }
-       int writeBytesWireFormat( byte[] dst, int dstIndex ) {
-               int start = dstIndex;
-
-               accountName = session.auth.username.toUpperCase();
-               primaryDomain = session.auth.domain.toUpperCase();
-               nativeOs = session.transport.client.nativeOs;
-               nativeLanMan = session.transport.client.nativeLanMan;
-
-               if( session.transport.server.security == SECURITY_USER &&
-                                               ( session.auth.hashesExternal ||
-                                               session.auth.password.length() > 0 )) {
-                       System.arraycopy( accountPassword, 0, dst, dstIndex, passwordLength );
-                       dstIndex += passwordLength;
-                       System.arraycopy( unicodePassword, 0, dst, dstIndex, unicodePasswordLength );
-                       dstIndex += unicodePasswordLength;
-               }
-               if( useUnicode ) {
-                       // at least NT 4 observed needing this only with unicode
-                       dst[dstIndex++] = (byte)'\0';
-               }
-
-               dstIndex += writeString( accountName, dst, dstIndex );
-               dstIndex += writeString( primaryDomain, dst, dstIndex );
-               dstIndex += writeString( nativeOs, dst, dstIndex );
-/*
-               // at least NT 4 observed with 2 zero bytes here
-               dst[dstIndex++] = (byte)0x00;
-               dst[dstIndex++] = (byte)0x00;
-This still isn't quite right.
-*/
-               dstIndex += writeString( nativeLanMan, dst, dstIndex );
-
-               return dstIndex - start;
-       }
-       int readParameterWordsWireFormat( byte[] buffer, int bufferIndex ) {
-               return 0;
-       }
-       int readBytesWireFormat( byte[] buffer, int bufferIndex ) {
-               return 0;
-       }
-       int readBytesDirectWireFormat( InputStream in, int byteCount ) throws IOException {
-               return 0;
-       }
-       public String toString() {
-               String result = new String( "SmbComSessionSetupAndX[" +
-                       super.toString() +
-                       ",maxBufferSize=" + negotiatedMaxBufferSize +
-                       ",maxMpxCount=" + negotiatedMaxMpxCount +
-                       ",vcNumber=" + vcNumber +
-                       ",sessionKey=" + sessionKey +
-                       ",passwordLength=" + passwordLength +
-                       ",unicodePasswordLength=" + unicodePasswordLength +
-                       ",capabilities=" + session.transport.client.capabilities +
-                       ",accountName=" + accountName +
-                       ",primaryDomain=" + primaryDomain +
-                       ",nativeOs=" + nativeOs +
-                       ",nativeLanMan=" + nativeLanMan + "]" );
-               return result;
-       }
-}
index 39c9ebb..3b4a443 100644 (file)
@@ -79,6 +79,10 @@ public class SmbException extends IOException {
  */
        public static final int ERRfilexists  = 80;
 /**
+ * Too many Uids active on this session
+ */
+       public static final int ERRtoomanyuids = 90;
+/**
  * The pipe has been ended
  */
        public static final int ERRbrokenpipe = 109;
@@ -154,6 +158,10 @@ public class SmbException extends IOException {
  * The device is not ready
  */
        public static final int ERRnotready = 21;
+/**
+ * General failure
+ */
+       public static final int ERRgeneral = 31;
 
        // RAP transaction status codes
        public static final int NERR_Success                = 0;
@@ -278,6 +286,9 @@ public class SmbException extends IOException {
                                        case ERRpasswordExpired:
                                                result += "The password of the user has expired";
                                                break;
+                                       case ERRtoomanyuids:
+                                               result += "Too many Uids active on this session";
+                                               break;
                                        default:
                                                result += "No description available [ERRSRV/" + errorCode + "]";
                                }
@@ -290,6 +301,9 @@ public class SmbException extends IOException {
                                        case ERRnotready:
                                                result += "The device is not ready";
                                                break;
+                                       case ERRgeneral:
+                                               result += "General failure";
+                                               break;
                                        default:
                                                result += "No description available [ERRHRD/" + errorCode + "]";
                                }
index e332cb2..add39d9 100644 (file)
@@ -1925,7 +1925,14 @@ The <tt>shareAccess</tt> parameter controls what permissions other clients have
  */
 
        public int hashCode() {
-               return url.hashCode();
+               int hash;
+               try {
+                       hash = getAddress().hashCode();
+               } catch( UnknownHostException uhe ) {
+                       hash = getServer().toUpperCase().hashCode();
+               }
+               getUncPath0();
+               return hash + canon.toUpperCase().hashCode();
        }
 
 /**
@@ -1950,7 +1957,6 @@ The <tt>shareAccess</tt> parameter controls what permissions other clients have
  */
 
        public boolean equals( Object obj ) {
-//HERE
                return obj instanceof SmbFile && obj.hashCode() == hashCode();
        }
 
index a9fa6d5..e3dbda3 100644 (file)
@@ -115,6 +115,14 @@ synchronized( transport ) {
                        return;
                }
 
+               transport.negotiate();
+
+               if( transport.useSigning && transport.macSigningKey == null ) {
+                    /* The first SMB_COM_SESSION_SETUP_ANX
+                     * generates the signing key */
+                       transport.initSigning( auth );
+               }
+
                Log.println( Log.WARNINGS, "smb session setup warning",
                                        " requesting session with accountName=" + auth.username +
                                        ",primaryDomain=" + auth.domain );
index af7f2db..2fa76af 100644 (file)
@@ -31,7 +31,12 @@ import java.io.InterruptedIOException;
 import java.net.InetAddress;
 import java.net.SocketException;
 import java.net.UnknownHostException;
+
+import java.security.MessageDigest;
+
 import java.util.Vector;
+import java.util.LinkedList;
+import java.util.ListIterator;
 import java.util.Enumeration;
 import java.util.Hashtable;
 
@@ -43,6 +48,10 @@ class SmbTransport implements Runnable {
        private static final int PUSHBACK_BUF_SIZE     = 64;
        private static final int DEFAULT_RCV_BUF_SIZE  = 60416;
        private static final int DEFAULT_SND_BUF_SIZE  = 5000;
+       private static final int DEFAULT_SSN_LIMIT     = 100;
+
+       private static final int LM_COMPATIBILITY =
+                       Config.getInt("jcifs.smb.lmCompatibility", 0);
 
        static final int MID_OFFSET      = 30;
        static final int HEADER_LENGTH   = 32;
@@ -59,16 +68,22 @@ class SmbTransport implements Runnable {
        private Thread thread;
        private Object outLock;
 
+    private MessageDigest signingDigest;
+
        private static Vector connections = new Vector();
        private static MpxControl mpxCtrl = new MpxControl();
 
 private static byte[] snd_buf = new byte[0xFFFF];
 private static byte[] rcv_buf = new byte[0xFFFF];
 
-       Vector sessions;
-       boolean negotiated, useUnicode;
+       LinkedList sessions;
+       boolean negotiated, useUnicode, useSigning;
 
        UniAddress address;
+
+    byte[] macSigningKey;
+    int signSequence;
+
        int port, rcv_buf_size, snd_buf_size;
 
        int negotiatedDialectIndex;
@@ -76,6 +91,8 @@ private static byte[] rcv_buf = new byte[0xFFFF];
        int negotiatedMaxBufferSize;
        int negotiatedCapabilities;
 
+       int ssnLimit = Config.getInt( "jcifs.smb.client.ssnLimit", DEFAULT_SSN_LIMIT );
+
        ClientProperties client = new ClientProperties();
        ServerProperties server = new ServerProperties();
 
@@ -90,8 +107,7 @@ private static byte[] rcv_buf = new byte[0xFFFF];
                 * but we could do raw and mpx
                 */
                int flags2 = Config.getInt( "jcifs.smb.client.flags2",
-                               ServerMessageBlock.FLAGS2_LONG_FILENAMES |
-                                                                                                       ServerMessageBlock.FLAGS2_UNICODE );
+                               ServerMessageBlock.FLAGS2_LONG_FILENAMES | ServerMessageBlock.FLAGS2_UNICODE );
                int capabilities = Config.getInt( "jcifs.smb.client.capabilities",
                                ServerMessageBlock.CAP_UNICODE | ServerMessageBlock.CAP_NT_SMBS );
                String nativeOs = Config.getProperty( "jcifs.smb.client.nativeOs",
@@ -161,12 +177,16 @@ private static byte[] rcv_buf = new byte[0xFFFF];
                if( Config.getBoolean( "jcifs.smb.client.useNTSmbs", false ) == true ) {
                        client.capabilities |= ServerMessageBlock.CAP_NT_SMBS;
                }
+               useSigning = Config.getBoolean("jcifs.smb.client.signingPreferred", false);
+               if( useSigning ) {
+            client.flags2 |= ServerMessageBlock.FLAGS2_SECURITY_SIGNATURES;
+               }
 
                soTimeout = Config.getInt( "jcifs.smb.client.soTimeout", DEFAULT_SO_TIMEOUT );
                responseTimeout = Config.getInt( "jcifs.smb.client.responseTimeout", DEFAULT_RESPONSE_TIMEOUT );
                rcv_buf_size = Config.getInt( "jcifs.smb.client.rcv_buf_size", DEFAULT_RCV_BUF_SIZE );
                snd_buf_size = client.maxBufferSize;
-               sessions = new Vector();
+               sessions = new LinkedList();
                responseTable = new Hashtable();
                outLock = new Object();
                negotiated = false;
@@ -178,16 +198,27 @@ private static byte[] rcv_buf = new byte[0xFFFF];
        synchronized SmbSession getSmbSession( NtlmPasswordAuthentication auth ) {
                SmbSession ssn;
 
-               for( Enumeration e = sessions.elements(); e.hasMoreElements(); ) {
-                       ssn = (SmbSession)e.nextElement();
+               ListIterator iter = sessions.listIterator();
+               while( iter.hasNext() ) {
+                       ssn = (SmbSession)iter.next();
                        if( ssn.matches( auth )) {
                                ssn.auth = auth;
                                return ssn;
                        }
                }
                ssn = new SmbSession( this, auth );
-//System.err.println( "SESSION+: " + ssn + "\n    " + sessions.toString() );
-               sessions.addElement( ssn );
+               sessions.add( ssn );
+
+               if( sessions.size() > ssnLimit ) {
+                       int nclose = sessions.size() / 10;
+                       SmbSession s;
+
+                       while( nclose-- > 0 ) {
+                               s = (SmbSession)sessions.removeFirst();
+                               s.logoff( false );
+                       }
+               }
+
                return ssn;
        }
        boolean matches( UniAddress address, int port, InetAddress localAddr, int localPort ) {
@@ -273,8 +304,10 @@ private static byte[] rcv_buf = new byte[0xFFFF];
                if( socket == null ) {
                        inError = true;
                }
-               for( Enumeration e = sessions.elements(); e.hasMoreElements(); ) {
-                       ssn = (SmbSession)e.nextElement();
+
+               ListIterator iter = sessions.listIterator();
+               while( iter.hasNext() ) {
+                       ssn = (SmbSession)iter.next();
                        ssn.logoff( inError );
                }
                if( socket != null ) {
@@ -366,6 +399,9 @@ synchronized( rcv_buf ) {
 
                                                        if( response.errorCode != 0 || e.hasMoreElements() == false ) {
                                                                ((SmbComTransactionResponse)response).hasMore = false;
+                                                               if( useSigning ) {
+                                       verify(rcv_buf, 0, response.length, response.verifySequence);
+                                                               }
                                                                response.notify();
                                                        } else {
                                                                ensureOpen();
@@ -381,6 +417,9 @@ synchronized( rcv_buf ) {
                                                                Log.printMessageData( "smb andx data", smb );
                                                        }
                                                        Log.printHexDump( "smb received", rcv_buf, 0, response.length );
+                                                       if( useSigning ) {
+                               verify(rcv_buf, 0, response.length, response.verifySequence);
+                                                       }
 
                                                        response.notify();
                                                }
@@ -403,6 +442,108 @@ synchronized( rcv_buf ) {
                        }
                }
        }
+
+    void initSigning(NtlmPasswordAuthentication auth) throws SmbException {
+               if( auth.hashesExternal ) {
+                       if( server.signaturesRequired ) {
+                               throw new SmbException( SmbException.ERRCLI, SmbException.ERRioe,
+                                               "Signing is required by the server but passwords are external." );
+                       }
+                       useSigning = false;
+                       return;
+               }
+
+               signSequence = 0;
+
+               switch (LM_COMPATIBILITY) {
+               case 0:
+               case 1:
+               case 2:
+                       macSigningKey = new byte[40];
+                       try {
+                               auth.getUserSessionKey(server.encryptionKey, macSigningKey, 0);
+                               System.arraycopy(auth.getUnicodeHash(server.encryptionKey),
+                                               0, macSigningKey, 16, 24);
+                       } catch (Exception ex) {
+                               Log.printStackTrace("Unable to calculate MAC signing key.", ex);
+                               macSigningKey = null;
+                       }
+                       break;
+               case 3:
+               case 4:
+               case 5:
+                       // NTLMv2 will have a key; LMv2 doesn't (just uses an
+                       // empty user session key).  So if/when we start doing
+                       // NTLMv2, this will change.
+                       macSigningKey = new byte[16];
+                       break;
+               default:
+                       macSigningKey = new byte[40];
+                       try {
+                               auth.getUserSessionKey(server.encryptionKey, macSigningKey, 0);
+                               System.arraycopy(auth.getUnicodeHash(server.encryptionKey),
+                                               0, macSigningKey, 16, 24);
+                       } catch (Exception ex) {
+                               Log.printStackTrace("Unable to calculate MAC signing key.", ex);
+                               macSigningKey = null;
+                       }
+                       break;
+               }
+       }
+
+    /**
+     * Performs MAC signing of the SMB.  This is done as follows.
+     * The signature field of the SMB is overwritted with the sequence number;
+     * The MD5 digest of the MAC signing key + the entire SMB is taken;
+     * The first 8 bytes of this are placed in the signature field.
+     *
+     * @param data The data.
+     * @param offset The starting offset at which the SMB header begins.
+     * @param length The length of the SMB data starting at offset. 
+     */
+    private void sign(byte[] data, int offset, int length) {
+               if (macSigningKey == null) return;
+               try {
+                       signingDigest.update(macSigningKey);
+                       int index = offset + ServerMessageBlock.SIGNATURE_OFFSET;
+                       for (int i = 0; i < 8; i++) data[index + i] = 0;
+                       ServerMessageBlock.writeInt4(signSequence, data, index);
+                       signingDigest.update(data, offset, length);
+                       System.arraycopy(signingDigest.digest(), 0, data, index, 8);
+               } catch (Exception ex) {
+                       Log.printStackTrace("Error signing SMB.", ex);
+               } finally {
+                       signSequence += 2;
+               }
+    } 
+
+    /**
+     * Performs MAC signature verification.  This calculates the signature
+     * of the SMB and compares it to the signature field on the SMB itself.
+     *
+     * @param data The data.
+     * @param offset The starting offset at which the SMB header begins.
+     * @param length The length of the SMB data starting at offset. 
+     */
+    private void verify(byte[] data, int offset, int length, int verifySequence) throws IOException {
+               if (macSigningKey == null) return;
+               signingDigest.update(macSigningKey);
+               int index = offset;
+               signingDigest.update(data, index, ServerMessageBlock.SIGNATURE_OFFSET); 
+               index += ServerMessageBlock.SIGNATURE_OFFSET;
+               byte[] sequence = new byte[8]; 
+               ServerMessageBlock.writeInt4(verifySequence, sequence, 0); 
+               signingDigest.update(sequence); 
+               index += 8;
+               signingDigest.update(data, index, length - ServerMessageBlock.SIGNATURE_OFFSET - 8);
+               byte[] signature = signingDigest.digest();
+               for (int i = 0; i < 8; i++) {
+                       if (signature[i] != data[offset + ServerMessageBlock.SIGNATURE_OFFSET + i]) {
+                               throw new IOException("Unverifiable signature.");
+                       }
+               }
+    } 
+
        void send( ServerMessageBlock request,
                                                        ServerMessageBlock response ) throws SmbException {
                Integer mid = null;
@@ -418,7 +559,11 @@ synchronized( rcv_buf ) {
                                synchronized( outLock ) {
                                        ensureOpen();
 synchronized( snd_buf ) {
-                                       out.write( snd_buf, 0, request.writeWireFormat( snd_buf, 0 ));
+                    int length = request.writeWireFormat(snd_buf, 0);
+                    if( useSigning ) {
+                        sign(snd_buf, 0, length);
+                    }
+                    out.write(snd_buf, 0, length);
                                        out.flush();
 
                                        Log.printMessageData( "smb sent", request );
@@ -452,7 +597,12 @@ synchronized( snd_buf ) {
                                synchronized( outLock ) {
                                        ensureOpen();
 synchronized( snd_buf ) {
-                                       out.write( snd_buf, 0, request.writeWireFormat( snd_buf, 0 ));
+                    int length = request.writeWireFormat(snd_buf, 0);
+                    if( useSigning ) {
+                                               response.verifySequence = signSequence + 1;
+                                               sign(snd_buf, 0, length);
+                    }
+                    out.write(snd_buf, 0, length);
                                        out.flush();
 
                                        Log.printMessageData( "smb sent", request );
@@ -541,7 +691,12 @@ synchronized( snd_buf ) {
                                        synchronized( outLock ) {
                                                ensureOpen();
 synchronized(snd_buf) {
-                                               out.write( snd_buf, 0, request.writeWireFormat( snd_buf, 0 ));
+                        int length = request.writeWireFormat(snd_buf, 0);
+                        if( useSigning ) {
+                                                       response.verifySequence = signSequence + 1;
+                            sign(snd_buf, 0, length);
+                        }
+                        out.write(snd_buf, 0, length);
                                                out.flush();
 
                                                Log.printMessageData( "smb sent", request );
@@ -586,7 +741,12 @@ synchronized(snd_buf) {
                                        synchronized( outLock ) {
                                                ensureOpen();
 synchronized( snd_buf ) {
-                                               out.write( snd_buf, 0, request.writeWireFormat( snd_buf, 0 ));
+                        int length = request.writeWireFormat(snd_buf, 0);
+                        if( useSigning ) {
+                                                       response.verifySequence = signSequence + 1;
+                            sign(snd_buf, 0, length);
+                        }
+                        out.write(snd_buf, 0, length);
                                                out.flush();
 
                                                Log.printMessageData( "smb sent", request );
@@ -661,6 +821,9 @@ synchronized( snd_buf ) {
                 * Negotiate Protocol Request / Response
                 */
 
+        // reset MAC signing
+        macSigningKey = null;
+
                SmbComNegotiateResponse response = new SmbComNegotiateResponse();
                send( new SmbComNegotiate(), response );
 
@@ -674,6 +837,22 @@ synchronized( snd_buf ) {
                server.encryptedPasswords  = response.encryptedPasswords;
                server.signaturesEnabled   = response.signaturesEnabled;
                server.signaturesRequired  = response.signaturesRequired;
+        if (server.signaturesRequired || (server.signaturesEnabled && useSigning)) {
+                       useSigning = true;
+            client.flags2 |= ServerMessageBlock.FLAGS2_SECURITY_SIGNATURES;
+
+                       if (signingDigest == null) {
+                               try {
+                                       signingDigest = MessageDigest.getInstance("MD5");
+                               } catch (Exception ex) {
+                                       Log.printStackTrace("Unable to obtain MD5 digest.", ex);
+                                       return;
+                               }
+                       }
+        } else {
+                       useSigning = false;
+            client.flags2 &= 0xFFFF ^ ServerMessageBlock.FLAGS2_SECURITY_SIGNATURES;
+               }
                negotiatedDialectIndex     = response.dialectIndex;;
                server.maxMpxCount         = response.maxMpxCount;
                negotiatedMaxMpxCount      = client.maxMpxCount < server.maxMpxCount ?
diff --git a/src/jcifs/smb/SmbTransport.java.bak b/src/jcifs/smb/SmbTransport.java.bak
new file mode 100644 (file)
index 0000000..d9501e4
--- /dev/null
@@ -0,0 +1,832 @@
+/* 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 jcifs.netbios.NbtSocket;
+import jcifs.netbios.NbtException;
+import jcifs.netbios.NbtAddress;
+import jcifs.UniAddress;
+import jcifs.Config;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PushbackInputStream;
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.InetAddress;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.Vector;
+import java.util.LinkedList;
+import java.util.ListIterator;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+class SmbTransport implements Runnable {
+
+       private static final int DEFAULT_MAX_MPX_COUNT = 10;
+       private static final int DEFAULT_RESPONSE_TIMEOUT = 10000;
+       private static final int DEFAULT_SO_TIMEOUT    = 15000;
+       private static final int PUSHBACK_BUF_SIZE     = 64;
+       private static final int DEFAULT_RCV_BUF_SIZE  = 60416;
+       private static final int DEFAULT_SND_BUF_SIZE  = 5000;
+       private static final int DEFAULT_SSN_LIMIT     = 100;
+
+       static final int MID_OFFSET      = 30;
+       static final int HEADER_LENGTH   = 32;
+       static final int FLAGS_OFFSET    = 9;
+       static final int FLAGS_RESPONSE  = 0x80;
+
+       private NbtSocket socket; // should become UniSocket?
+       private InputStream in;
+       private OutputStream out;
+       private int localPort, soTimeout, responseTimeout;
+       private long closeTime;
+       private InetAddress localAddr;
+       private Hashtable responseTable;
+       private Thread thread;
+       private Object outLock;
+
+       private static Vector connections = new Vector();
+       private static MpxControl mpxCtrl = new MpxControl();
+
+private static byte[] snd_buf = new byte[0xFFFF];
+private static byte[] rcv_buf = new byte[0xFFFF];
+
+       LinkedList sessions;
+       boolean negotiated, useUnicode;
+
+       UniAddress address;
+       int port, rcv_buf_size, snd_buf_size;
+
+       int negotiatedDialectIndex;
+       int negotiatedMaxMpxCount;
+       int negotiatedMaxBufferSize;
+       int negotiatedCapabilities;
+
+       int ssnLimit = Config.getInt( "jcifs.smb.client.ssnLimit", DEFAULT_SSN_LIMIT );
+
+       ClientProperties client = new ClientProperties();
+       ServerProperties server = new ServerProperties();
+
+       class ClientProperties {
+               int maxMpxCount = Config.getInt( "jcifs.smb.client.maxMpxCount",
+                                                                                                       DEFAULT_MAX_MPX_COUNT );
+               int maxBufferSize = Config.getInt( "jcifs.smb.client.snd_buf_size",
+                                                                                                       DEFAULT_SND_BUF_SIZE );
+               int sessionKey = 0x00000000;
+               /* NT 4 Workstation client capabilities 0x00D4
+                * we don't do NT Status Codes or Level II oplocks
+                * but we could do raw and mpx
+                */
+               int flags2 = Config.getInt( "jcifs.smb.client.flags2",
+                               ServerMessageBlock.FLAGS2_LONG_FILENAMES |
+                                                                                                       ServerMessageBlock.FLAGS2_UNICODE );
+               int capabilities = Config.getInt( "jcifs.smb.client.capabilities",
+                               ServerMessageBlock.CAP_UNICODE | ServerMessageBlock.CAP_NT_SMBS );
+               String nativeOs = Config.getProperty( "jcifs.smb.client.nativeOs",
+                               System.getProperty( "os.name" ));
+               String nativeLanMan = Config.getProperty( "jcifs.smb.client.nativeLanMan", "jCIFS" );
+               int vcNumber = 1;
+       }
+       class ServerProperties {
+               String tconHostName;
+
+               byte flags;
+               int flags2;
+               int maxMpxCount;
+               int maxBufferSize;
+               int sessionKey;
+               // NT 4 Workstation is 0x43FD
+               int capabilities;
+               String oemDomainName;
+               String primaryDomain;
+               String nativeOs;
+               String nativeLanMan;
+
+               int securityMode;
+               int security;
+               boolean encryptedPasswords;
+               boolean signaturesEnabled;
+               boolean signaturesRequired;
+               int maxNumberVcs;
+               int maxRawSize;
+               long serverTime;
+               int serverTimeZone;
+               int encryptionKeyLength;
+               byte[] encryptionKey;
+       }
+
+       static synchronized SmbTransport getSmbTransport( UniAddress address, int port ) {
+               return getSmbTransport( address, port,
+                                                       Config.getInetAddress( "jcifs.smb.client.laddr", null ),
+                                                       Config.getInt( "jcifs.smb.client.lport", 0 ));
+       }
+       static synchronized SmbTransport getSmbTransport( UniAddress address, int port,
+                                                                       InetAddress localAddr, int localPort ) {
+               SmbTransport conn;
+               for( Enumeration e = connections.elements(); e.hasMoreElements(); ) {
+                       conn = (SmbTransport)e.nextElement();
+                       if( conn.matches( address, port, localAddr, localPort )) {
+                               return conn;
+                       }
+               }
+
+               conn = new SmbTransport( address, port, localAddr, localPort );
+               connections.addElement( conn );
+               return conn;
+       }
+
+       SmbTransport( UniAddress address, int port, InetAddress localAddr, int localPort ) {
+               this.address = address;
+               this.port = port;
+               this.localAddr = localAddr;
+               this.localPort = localPort;
+
+               useUnicode = Config.getBoolean( "jcifs.smb.client.useUnicode", true );
+               if( useUnicode == false ) {
+                       client.flags2 &= 0xFFFF ^ ServerMessageBlock.FLAGS2_UNICODE;
+                       client.capabilities &= 0xFFFF ^ ServerMessageBlock.CAP_UNICODE;
+               }
+               if( Config.getBoolean( "jcifs.smb.client.useNTSmbs", false ) == true ) {
+                       client.capabilities |= ServerMessageBlock.CAP_NT_SMBS;
+               }
+
+               soTimeout = Config.getInt( "jcifs.smb.client.soTimeout", DEFAULT_SO_TIMEOUT );
+               responseTimeout = Config.getInt( "jcifs.smb.client.responseTimeout", DEFAULT_RESPONSE_TIMEOUT );
+               rcv_buf_size = Config.getInt( "jcifs.smb.client.rcv_buf_size", DEFAULT_RCV_BUF_SIZE );
+               snd_buf_size = client.maxBufferSize;
+               sessions = new LinkedList();
+               responseTable = new Hashtable();
+               outLock = new Object();
+               negotiated = false;
+       }
+
+       synchronized SmbSession getSmbSession() {
+               return getSmbSession( new NtlmPasswordAuthentication( null, null, null ));
+       }
+       synchronized SmbSession getSmbSession( NtlmPasswordAuthentication auth ) {
+               SmbSession ssn;
+
+               ListIterator iter = sessions.listIterator();
+               while( iter.hasNext() ) {
+                       ssn = (SmbSession)iter.next();
+                       if( ssn.matches( auth )) {
+                               ssn.auth = auth;
+                               return ssn;
+                       }
+               }
+               ssn = new SmbSession( this, auth );
+               sessions.add( ssn );
+
+               if( sessions.size() > ssnLimit ) {
+                       int nclose = sessions.size() / 10;
+                       SmbSession s;
+
+                       while( nclose-- > 0 ) {
+                               s = (SmbSession)sessions.removeFirst();
+                               s.logoff( false );
+                       }
+               }
+
+               return ssn;
+       }
+       boolean matches( UniAddress address, int port, InetAddress localAddr, int localPort ) {
+               InetAddress defaultLocal = null;
+               try {
+                       defaultLocal = InetAddress.getLocalHost();
+               } catch( UnknownHostException uhe ) {
+               }
+               int p1 = ( port == 0 || port == 139 ) ? 0 : port;
+               int p2 = ( this.port == 0 || this.port == 139 ) ? 0 : this.port;
+               InetAddress la1 = localAddr == null ? defaultLocal : localAddr;
+               InetAddress la2 = this.localAddr == null ? defaultLocal : this.localAddr;
+               return address.equals( this.address ) &&
+                                       p1 == p2 &&
+                                       la1.equals( la2 ) &&
+                                       localPort == this.localPort;
+       }
+       boolean hasCapability( int cap ) throws SmbException {
+               negotiate();
+               return (negotiatedCapabilities & cap) == cap;
+       }
+       void ensureOpen() throws IOException {
+               if( socket == null ) {
+                       Object obj;
+                       NbtAddress naddr;
+                       String calledName;
+
+                       /* Hack to convert InetAddress to NbtAddress until we properly
+                        * abstract NetBIOSless transport with some kind of "UniSocket".
+                        */
+                       obj = address.getAddress();
+                       if( obj instanceof NbtAddress ) {
+                               naddr = (NbtAddress)obj;
+                       } else {
+                               try {
+                                       naddr = NbtAddress.getByName( ((InetAddress)obj).getHostAddress() );
+                               } catch( UnknownHostException uhe ) {
+                                       naddr = null; // never happen
+                               }
+                       }
+
+                       calledName = address.firstCalledName();
+                       do {
+                               try {
+                                       socket = new NbtSocket( naddr, calledName, port, localAddr, localPort );
+                                       break;
+                               } catch( NbtException ne ) {
+                                       if( ne.errorClass == NbtException.ERR_SSN_SRVC &&
+                                                               ( ne.errorCode == NbtException.CALLED_NOT_PRESENT ||
+                                                               ne.errorCode == NbtException.NOT_LISTENING_CALLED )) {
+                                               Log.println( Log.WARNINGS, "smb warning", ne.getMessage() );
+                                       } else {
+                                               throw ne;
+                                       }
+                               }
+                       } while(( calledName = address.nextCalledName()) != null );
+
+                       if( calledName == null ) {
+                               throw new IOException( "Failed to establish session with " + address );
+                       }
+
+                       /* Save the calledName for using on SMB_COM_TREE_CONNECT
+                        */
+                       if( calledName == NbtAddress.SMBSERVER_NAME ) {
+                               server.tconHostName = address.getHostAddress();
+                       } else {
+                               server.tconHostName = calledName;
+                       }
+
+                       if( Config.getBoolean( "jcifs.smb.client.tcpNoDelay", false )) {
+                               socket.setTcpNoDelay( true );
+                       }
+                       in = new PushbackInputStream( socket.getInputStream(), PUSHBACK_BUF_SIZE );
+                       out = socket.getOutputStream();
+                       thread = new Thread( this, "JCIFS-SmbTransport" );
+                       thread.setDaemon( true );
+                       thread.start();
+               }
+       }
+       void tryClose( boolean inError ) {
+               SmbSession ssn;
+
+               if( socket == null ) {
+                       inError = true;
+               }
+
+               ListIterator iter = sessions.listIterator();
+               while( iter.hasNext() ) {
+                       ssn = (SmbSession)iter.next();
+                       ssn.logoff( inError );
+               }
+               if( socket != null ) {
+                       try {
+                               socket.close();
+                       } catch( IOException ioe ) {
+                       }
+               }
+               in = null;
+               out = null;
+               socket = null;
+               negotiated = false;
+               thread = null;
+               responseTable.clear();
+       }
+       public void run() {
+               int mid, l, i, n, m;
+               ServerMessageBlock response;
+               int magic[] = { 0xFF, 'S', 'M', 'B' };
+
+               while( thread == Thread.currentThread() ) {
+                       try {
+                               socket.setSoTimeout( soTimeout );
+
+                               m = 0;
+                               while( m < 4 ) {
+                                       if(( i = in.read() ) < 0 ) {
+                                               return;
+                                       }
+                                       if(( i & 0xFF ) == magic[m] ) {
+                                               m++;
+                                       } else if(( i & 0xFF ) == 0xFF ) {
+                                               m = 1;
+                                       } else {
+                                               m = 0;
+                                       }
+                               }
+
+synchronized( rcv_buf ) {
+                               rcv_buf[0] = (byte)0xFF;
+                               rcv_buf[1] = (byte)'S';
+                               rcv_buf[2] = (byte)'M';
+                               rcv_buf[3] = (byte)'B';
+
+                               if( in.read( rcv_buf, 4, HEADER_LENGTH - 4 ) != ( HEADER_LENGTH - 4 )) {
+                                       /* Read on a netbios SocketInputStream does not
+                                        * return until len bytes have been read or the stream is
+                                        * closed. This must be the latter case.
+                                        */
+                                       break;
+                               }
+                               ((PushbackInputStream)in).unread( rcv_buf, 0, HEADER_LENGTH );
+                               if( rcv_buf[0] != (byte)0xFF ||
+                                                               rcv_buf[1] != (byte)'S' ||
+                                                               rcv_buf[2] != (byte)'M' ||
+                                                               rcv_buf[3] != (byte)'B' ) {
+                                       Log.println( Log.WARNINGS, "smb warning",
+                                                                                               "bad smb header, purging session message" );
+                                       in.skip( in.available() );
+                                       continue;
+                               }
+                               if(( rcv_buf[FLAGS_OFFSET] & FLAGS_RESPONSE ) == FLAGS_RESPONSE ) {
+                                       mid = ServerMessageBlock.readInt2( rcv_buf, MID_OFFSET );
+
+                                       response = (ServerMessageBlock)responseTable.get( new Integer( mid ));
+                                       if( response == null ) {
+                                               Log.println( Log.WARNINGS, "smb warning",
+                                                               " no handler for mid=" + mid + ", purging session message" );
+                                               in.skip( in.available() );
+                                               continue;
+                                       }
+                                       synchronized( response ) {
+                                               response.useUnicode = useUnicode;
+                                               Log.println( Log.DEBUGGING, "smb transport warning",
+                                                                                                               " new data read from socket" );
+
+                                               if( response instanceof SmbComTransactionResponse ) {
+                                                       Enumeration e = (Enumeration)response;
+                                                       if( e.hasMoreElements() ) {
+                                                               e.nextElement();
+                                                       } else {
+                                                               Log.println( Log.WARNINGS, "smb warning",
+                                                                                       "more responses to transaction than expected" );
+                                                               continue;
+                                                       }
+                                                       response.readWireFormat( in, rcv_buf, 0 );
+                                                       response.received = true;
+                                                       Log.printMessageData( "smb received", response );
+
+                                                       if( response.errorCode != 0 || e.hasMoreElements() == false ) {
+                                                               ((SmbComTransactionResponse)response).hasMore = false;
+                                                               response.notify();
+                                                       } else {
+                                                               ensureOpen();
+                                                       }
+                                               } else {
+                                                       response.readWireFormat( in, rcv_buf, 0 );
+                                                       response.received = true;
+
+                                                       Log.printMessageData( "smb received", response );
+                                                       ServerMessageBlock smb = response;
+                                                       while( smb instanceof AndXServerMessageBlock &&
+                                                                       ( smb = ((AndXServerMessageBlock)smb).andx ) != null ) {
+                                                               Log.printMessageData( "smb andx data", smb );
+                                                       }
+                                                       Log.printHexDump( "smb received", rcv_buf, 0, response.length );
+
+                                                       response.notify();
+                                               }
+                                       }
+                               } else {
+                                       // it's a request(break oplock)
+                               }
+}
+                       } catch( InterruptedIOException iioe ) {
+                               if( responseTable.size() == 0 ) {
+                                       tryClose( false );
+                               } else {
+                                       Log.println( Log.WARNINGS, "smb warning",
+                                                               " soTimeout has occured but there are " +
+                                                               responseTable.size() + " pending requests" );
+                               }
+                       } catch( IOException ioe ) {
+                               tryClose( true );
+                               Log.printStackTrace( "exception reading from socket input: " + address, ioe );
+                       }
+               }
+       }
+       void send( ServerMessageBlock request,
+                                                       ServerMessageBlock response ) throws SmbException {
+               Integer mid = null;
+
+               negotiate();
+
+               request.flags2 = client.flags2;
+               request.mid = aquireMid();
+               request.useUnicode = useUnicode;
+
+               if( response == null ) {
+                       try {
+                               synchronized( outLock ) {
+                                       ensureOpen();
+synchronized( snd_buf ) {
+                                       out.write( snd_buf, 0, request.writeWireFormat( snd_buf, 0 ));
+                                       out.flush();
+
+                                       Log.printMessageData( "smb sent", request );
+                                       ServerMessageBlock smb = request;
+                                       while( smb instanceof AndXServerMessageBlock &&
+                                                                       ( smb = ((AndXServerMessageBlock)smb).andx ) != null ) {
+                                               Log.printMessageData( "smb andx data", smb );
+                                       }
+                                       Log.printHexDump( "smb sent", snd_buf, 0, request.length );
+}
+                               }
+                       } catch( IOException ioe ) {
+                               tryClose( true );
+                               throw new SmbException( SmbException.ERRCLI, SmbException.ERRioe, ioe.getMessage() );
+                       } finally {
+                               releaseMid( request.mid );
+                       }
+
+                       return;
+               }
+
+               // now for the normal case where response is not null
+
+               try {
+                       synchronized( response ) {
+
+                               response.received = false;
+                               mid = new Integer( request.mid );
+                               responseTable.put( mid, response );
+
+                               synchronized( outLock ) {
+                                       ensureOpen();
+synchronized( snd_buf ) {
+                                       out.write( snd_buf, 0, request.writeWireFormat( snd_buf, 0 ));
+                                       out.flush();
+
+                                       Log.printMessageData( "smb sent", request );
+                                       ServerMessageBlock smb = request;
+                                       while( smb instanceof AndXServerMessageBlock &&
+                                                                       ( smb = ((AndXServerMessageBlock)smb).andx ) != null ) {
+                                               Log.printMessageData( "smb andx data", smb );
+                                       }
+                                       Log.printHexDump( "smb sent", snd_buf, 0, request.length );
+}
+                               }
+
+                               // default it 1 so that 0 can be used as forever
+                               response.wait( response.responseTimeout == 1 ?
+                                                                                               responseTimeout : response.responseTimeout );
+                       }
+               } catch( InterruptedException ie ) {
+                       tryClose( true );
+               } catch( IOException ioe ) {
+                       tryClose( true );
+                       throw new SmbException( SmbException.ERRCLI, SmbException.ERRioe, ioe.getMessage() );
+               } finally {
+                       responseTable.remove( mid );
+                       releaseMid( request.mid );
+               }
+
+               if( response.received == false ) {
+                       tryClose( true );
+                       throw new SmbException( SmbException.ERRCLI,
+                                                                       SmbException.ERRserverTimeout,
+                                                                       address );
+               }
+               switch( response.errorCode & 0xFF ) {
+                       case SmbException.SUCCESS:
+                               break;
+                       case SmbException.ERRDOS:
+                               switch(( response.errorCode >> 16 ) & 0xFFFF ) {
+                                       case SmbException.ERRnoaccess:
+                                               throw new SmbAuthException( response.errorCode );
+                               }
+                               throw new SmbException( response.errorCode );
+                       case SmbException.ERRSRV:
+                               switch(( response.errorCode >> 16 ) & 0xFFFF ) {
+                                       case SmbException.ERRbadpw:
+                                       case SmbException.ERRaccess:
+                                       case SmbException.ERRaccountExpired:
+                                       case SmbException.ERRbadClient:
+                                       case SmbException.ERRbadLogonTime:
+                                       case SmbException.ERRpasswordExpired:
+                                               throw new SmbAuthException( response.errorCode );
+                               }
+                       default:
+                               throw new SmbException( response.errorCode );
+               }
+
+       }
+       void sendTransaction( SmbComTransaction request,
+                                                       SmbComTransactionResponse response ) throws SmbException {
+               Integer mid = null;
+
+               negotiate();
+
+               request.flags2 = client.flags2;
+               request.mid = aquireMid();
+               mid = new Integer( request.mid );
+               request.useUnicode = useUnicode;
+               request.maxBufferSize = negotiatedMaxBufferSize;
+               response.received = false;
+               response.hasMore = true;
+               response.isPrimary = true;
+
+               try {
+                       request.txn_buf = BufferCache.getBuffer();
+                       response.txn_buf = BufferCache.getBuffer();
+
+                       request.nextElement();
+                       if( request.hasMoreElements() ) {
+                               // multi-part request
+
+                               SmbComBlankResponse interimResponse = new SmbComBlankResponse();
+
+                               synchronized( interimResponse ) {
+
+                                       responseTable.put( mid, interimResponse );
+
+                                       synchronized( outLock ) {
+                                               ensureOpen();
+synchronized(snd_buf) {
+                                               out.write( snd_buf, 0, request.writeWireFormat( snd_buf, 0 ));
+                                               out.flush();
+
+                                               Log.printMessageData( "smb sent", request );
+                                               Log.printHexDump( "smb sent", snd_buf, 0, request.length );
+}
+                                       }
+
+                                       interimResponse.wait( responseTimeout );
+
+                                       if( interimResponse.received == false ) {
+                                               throw new SmbException( SmbException.ERRserverTimeout );
+                                       }
+                                       switch( interimResponse.errorCode & 0xFF ) {
+                                               case SmbException.SUCCESS:
+                                                       break;
+                                               case SmbException.ERRDOS:
+                                                       switch(( response.errorCode >> 16 ) & 0xFFFF ) {
+                                                               case SmbException.ERRnoaccess:
+                                                                       throw new SmbAuthException( response.errorCode );
+                                                       }
+                                                       throw new SmbException( response.errorCode );
+                                               case SmbException.ERRSRV:
+                                                       switch(( interimResponse.errorCode >> 16 ) & 0xFFFF ) {
+                                                               case SmbException.ERRbadpw:
+                                                               case SmbException.ERRaccess:
+                                                               case SmbException.ERRaccountExpired:
+                                                               case SmbException.ERRbadClient:
+                                                               case SmbException.ERRbadLogonTime:
+                                                               case SmbException.ERRpasswordExpired:
+                                                                       throw new SmbAuthException( interimResponse.errorCode );
+                                                       }
+                                               default:
+                                                       throw new SmbException( interimResponse.errorCode );
+                                       }
+                               }
+                               request.nextElement();
+                       }
+
+                       synchronized( response ) {
+                               responseTable.put( mid, response );
+                               do {
+                                       synchronized( outLock ) {
+                                               ensureOpen();
+synchronized( snd_buf ) {
+                                               out.write( snd_buf, 0, request.writeWireFormat( snd_buf, 0 ));
+                                               out.flush();
+
+                                               Log.printMessageData( "smb sent", request );
+                                               Log.printHexDump( "smb sent", snd_buf, 0, request.length );
+}
+                                       }
+                               } while( request.hasMoreElements() && request.nextElement() != null );
+
+                               do {
+                                       // default it 1 so that 0 can be used as forever
+                                       response.received = false;
+                                       response.wait( response.responseTimeout == 1 ? responseTimeout : response.responseTimeout );
+                               } while( response.received && response.hasMoreElements() );
+                       }
+               } catch( InterruptedException ie ) {
+                       tryClose( true );
+               } catch( IOException ioe ) {
+                       tryClose( true );
+                       throw new SmbException( SmbException.ERRCLI, SmbException.ERRioe, ioe.getMessage() );
+               } finally {
+                       responseTable.remove( mid );
+                       releaseMid( request.mid );
+                       BufferCache.releaseBuffer( request.txn_buf );
+                       BufferCache.releaseBuffer( response.txn_buf );
+               }
+
+               if( response.received == false ) {
+                       tryClose( true );
+                       throw new SmbException( SmbException.ERRCLI,
+                                                                       SmbException.ERRserverTimeout,
+                                                                       address );
+               }
+               switch( response.errorCode & 0xFF ) {
+                       case SmbException.SUCCESS:
+                               break;
+                       case SmbException.ERRDOS:
+                               switch(( response.errorCode >> 16 ) & 0xFFFF ) {
+                                       case SmbException.ERRnoaccess:
+                                               throw new SmbAuthException( response.errorCode );
+                               }
+                               throw new SmbException( response.errorCode );
+                       case SmbException.ERRSRV:
+                               switch(( response.errorCode >> 16 ) & 0xFFFF ) {
+                                       case SmbException.ERRbadpw:
+                                       case SmbException.ERRaccess:
+                                       case SmbException.ERRaccountExpired:
+                                       case SmbException.ERRbadClient:
+                                       case SmbException.ERRbadLogonTime:
+                                       case SmbException.ERRpasswordExpired:
+                                               throw new SmbAuthException( response.errorCode );
+                               }
+                       default:
+                               throw new SmbException( response.errorCode );
+               }
+       }
+       synchronized void negotiate() throws SmbException {
+
+               if( negotiated ) {
+                       return;
+               }
+               /* we must set this here rather than later because this
+                * calls send() which calls negotiate so we don't want to
+                * end up in a loop. The alternative would be to inline
+                * the send routine here but this seems okay for now
+                */
+               negotiated = true;
+
+               Log.println( Log.WARNINGS, "smb negotiation warning",
+                                                       " requesting negotiation with " + address );
+
+               /*
+                * Negotiate Protocol Request / Response
+                */
+
+               SmbComNegotiateResponse response = new SmbComNegotiateResponse();
+               send( new SmbComNegotiate(), response );
+
+               if( response.dialectIndex > 10 ) {
+                       tryClose( true );
+                       throw new SmbException( SmbException.ERRCLI, SmbException.ERRbadDialect );
+               }
+
+               server.securityMode        = response.securityMode;
+               server.security            = response.security;
+               server.encryptedPasswords  = response.encryptedPasswords;
+               server.signaturesEnabled   = response.signaturesEnabled;
+               server.signaturesRequired  = response.signaturesRequired;
+               negotiatedDialectIndex     = response.dialectIndex;;
+               server.maxMpxCount         = response.maxMpxCount;
+               negotiatedMaxMpxCount      = client.maxMpxCount < server.maxMpxCount ?
+                                                                               client.maxMpxCount : server.maxMpxCount;
+               mpxCtrl.maxMpxCount        = negotiatedMaxMpxCount < 1 ?
+                                                                               1 : negotiatedMaxMpxCount;
+               server.maxNumberVcs        = response.maxNumberVcs;
+               server.maxBufferSize       = response.maxBufferSize;
+               negotiatedMaxBufferSize    = client.maxBufferSize < server.maxBufferSize ?
+                                                                               client.maxBufferSize : server.maxBufferSize;
+               server.maxRawSize          = response.maxRawSize;
+               server.sessionKey          = response.sessionKey;
+               server.capabilities        = response.capabilities;
+               negotiatedCapabilities     = client.capabilities & server.capabilities;
+               if(( negotiatedCapabilities & ServerMessageBlock.CAP_UNICODE ) == 0 ) {
+                       // server doesn't want unicode
+                       if( Config.getBoolean( "jcifs.smb.client.useUnicode", false )) {
+                               // force unicode
+                               negotiatedCapabilities |= ServerMessageBlock.CAP_UNICODE;
+                       } else {
+                               // not explicitly set to true so flip unicode off as server requests
+                               useUnicode = false;
+                               client.flags2 &= 0xFFFF ^ ServerMessageBlock.FLAGS2_UNICODE;
+                       }
+               }
+               server.serverTime          = response.serverTime;
+               server.serverTimeZone      = response.serverTimeZone;
+               server.encryptionKeyLength = response.encryptionKeyLength;
+               server.encryptionKey       = response.encryptionKey;
+               server.oemDomainName       = response.oemDomainName;
+       }
+       public String toString() {
+               String ret = "SmbTransport[address=" + address;
+               if( socket == null ) {
+                       ret += ",port=,localAddr=,localPort=]";
+               } else {
+                       ret += ",port=" + socket.getPort() +
+                       ",localAddr=" + socket.getLocalAddress() +
+                       ",localPort=" + socket.getLocalPort() + "]";
+               }
+               return ret;
+       }
+
+       static int aquireMid() throws SmbException {
+               try {
+                       return mpxCtrl.aquireMid();
+               } catch( InterruptedException ie ) {
+                       throw new SmbException( SmbException.ERRCLI, SmbException.ERRioe, ie.getMessage() );
+               }
+       }
+       static void releaseMid( int mid ) {
+               mpxCtrl.releaseMid( mid );
+       }
+
+    static class MpxControl {
+               MpxListNode first, last;
+        class MpxListNode {
+            int i;  
+            MpxListNode next;
+                       MpxListNode( int id ) {
+                               i = id;
+                               next = null;
+                       }
+        }       
+               int nextMid, mpxCount, maxMpxCount;
+
+               MpxControl() {
+                       nextMid = 0;
+                       mpxCount = 0;
+                       maxMpxCount = 1;
+                       first = last = null;
+               }
+
+               synchronized void clear() {
+                       nextMid = 0;
+                       mpxCount = 0;
+                       maxMpxCount = 1;
+                       first = last = null;
+               }
+               synchronized int aquireMid() throws InterruptedException {
+                       while( mpxCount >= maxMpxCount ) {
+                               wait();
+                       }
+                       if(( ++nextMid % 0xFFFF ) == 0 ) {
+                               nextMid = 1;
+                       }
+                       add( nextMid );
+                       mpxCount++;
+                       return nextMid;
+               }
+               synchronized void releaseMid( int i ) {
+                       remove( i );
+                       mpxCount--;
+                       notify();
+               }
+        synchronized boolean contains( int i ) {
+                       for( MpxListNode tmp = first; tmp != null; tmp = tmp.next ) {
+                               if( tmp.i == i ) {
+                                       return true;
+                               }
+                       }
+                       return false;
+        }       
+        synchronized void add( int i ) {
+                       if( contains( i )) {
+                               return;
+                       }
+                       if( first == null ) {
+                               first = last = new MpxListNode( i );
+                       } else {
+                               last = last.next = new MpxListNode( i );
+                       }
+        }
+        synchronized void remove( int i ) {
+                       if( first == null ) {
+                               return;
+                       } else if( first == last && first.i == i ) {
+                               first = last = null;
+                               return;
+                       }
+                       MpxListNode tmp, prev;
+                       for( tmp = prev = first; tmp != null; tmp = tmp.next ) {
+                               if( tmp.i == i ) {
+                                       if( tmp == first ) {
+                                               first = first.next;
+                                       } else if( tmp == last ) {
+                                               last = prev;
+                                               last.next = null;
+                                       } else {
+                                               prev.next = tmp.next;
+                                       }
+                                       return;
+                               }
+                               prev = tmp;
+                       }
+        }       
+    }
+}
diff --git a/update/Base64.java b/update/Base64.java
deleted file mode 100644 (file)
index 9008667..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/* Encodes and decodes to and from Base64 notation.\r
- * Copyright (C) 2003 "Eric Glass" <jcifs at samba dot org>\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
- */\r
-\r
-package jcifs.util;\r
-\r
-public class Base64 {\r
-\r
-    private static final String ALPHABET =\r
-            "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";\r
-\r
-    /**\r
-     * Base-64 encodes the supplied block of data.  Line wrapping is not\r
-     * applied on output.\r
-     *\r
-     * @param bytes The block of data that is to be Base-64 encoded.\r
-     * @return A <code>String</code> containing the encoded data.\r
-     */\r
-    public static String encode(byte[] bytes) {\r
-        int length = bytes.length;\r
-        if (length == 0) return "";\r
-        StringBuffer buffer =\r
-                new StringBuffer((int) Math.ceil((double) length / 3d) * 4);\r
-        int remainder = length % 3;\r
-        length -= remainder;\r
-        int block;\r
-        int i = 0;\r
-        while (i < length) {\r
-            block = ((bytes[i++] & 0xff) << 16) | ((bytes[i++] & 0xff) << 8) |\r
-                    (bytes[i++] & 0xff);\r
-            buffer.append(ALPHABET.charAt(block >>> 18));\r
-            buffer.append(ALPHABET.charAt((block >>> 12) & 0x3f));\r
-            buffer.append(ALPHABET.charAt((block >>> 6) & 0x3f));\r
-            buffer.append(ALPHABET.charAt(block & 0x3f));\r
-        }\r
-        if (remainder == 0) return buffer.toString();\r
-        if (remainder == 1) {\r
-            block = (bytes[i] & 0xff) << 4;\r
-            buffer.append(ALPHABET.charAt(block >>> 6));\r
-            buffer.append(ALPHABET.charAt(block & 0x3f));\r
-            buffer.append("==");\r
-            return buffer.toString();\r
-        }\r
-        block = (((bytes[i++] & 0xff) << 8) | ((bytes[i]) & 0xff)) << 2;\r
-        buffer.append(ALPHABET.charAt(block >>> 12));\r
-        buffer.append(ALPHABET.charAt((block >>> 6) & 0x3f));\r
-        buffer.append(ALPHABET.charAt(block & 0x3f));\r
-        buffer.append("=");\r
-        return buffer.toString();\r
-    }\r
-\r
-    /**\r
-     * Decodes the supplied Base-64 encoded string.\r
-     *\r
-     * @param string The Base-64 encoded string that is to be decoded.\r
-     * @return A <code>byte[]</code> containing the decoded data block.\r
-     */\r
-    public static byte[] decode(String string) {\r
-        int length = string.length();\r
-        if (length == 0) return new byte[0];\r
-        int pad = (string.charAt(length - 2) == '=') ? 2 :\r
-                (string.charAt(length - 1) == '=') ? 1 : 0;\r
-        int size = length * 3 / 4 - pad;\r
-        byte[] buffer = new byte[size];\r
-        int block;\r
-        int i = 0;\r
-        int index = 0;\r
-        while (i < length) {\r
-            block = (ALPHABET.indexOf(string.charAt(i++)) & 0xff) << 18 |\r
-                    (ALPHABET.indexOf(string.charAt(i++)) & 0xff) << 12 |\r
-                    (ALPHABET.indexOf(string.charAt(i++)) & 0xff) << 6 |\r
-                    (ALPHABET.indexOf(string.charAt(i++)) & 0xff);\r
-            buffer[index++] = (byte) (block >>> 16);\r
-            if (index < size) buffer[index++] = (byte) ((block >>> 8) & 0xff);\r
-            if (index < size) buffer[index++] = (byte) (block & 0xff);\r
-        }\r
-        return buffer;\r
-    }\r
-\r
-}\r
diff --git a/update/HMACT64.java b/update/HMACT64.java
deleted file mode 100644 (file)
index 8420fb9..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/* HMACT64 keyed hashing algorithm\r
- * Copyright (C) 2003 "Eric Glass" <jcifs at samba dot org>\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
- */\r
-\r
-package jcifs.util;\r
-\r
-import java.security.MessageDigest;\r
-\r
-/**\r
- * This is an implementation of the HMACT64 keyed hashing algorithm.\r
- * HMACT64 is defined by Luke Leighton as a modified HMAC-MD5 (RFC 2104)\r
- * in which the key is truncated at 64 bytes (rather than being hashed\r
- * via MD5).\r
- */ \r
-public class HMACT64 extends MessageDigest implements Cloneable {\r
-\r
-    private static final int BLOCK_LENGTH = 64;\r
-\r
-    private static final byte IPAD = (byte) 0x36;\r
-\r
-    private static final byte OPAD = (byte) 0x5c;\r
-\r
-    private MessageDigest md5;\r
-\r
-    private byte[] ipad = new byte[BLOCK_LENGTH];\r
-\r
-    private byte[] opad = new byte[BLOCK_LENGTH];\r
-\r
-    /**\r
-     * Creates an HMACT64 instance which uses the given secret key material.\r
-     *\r
-     * @param key The key material to use in hashing.\r
-     */\r
-    public HMACT64(byte[] key) {\r
-        super("HMACT64");\r
-        int length = Math.min(key.length, BLOCK_LENGTH);\r
-        for (int i = 0; i < length; i++) {\r
-            ipad[i] = (byte) (key[i] ^ IPAD);\r
-            opad[i] = (byte) (key[i] ^ OPAD);\r
-        }\r
-        for (int i = length; i < BLOCK_LENGTH; i++) {\r
-            ipad[i] = IPAD;\r
-            opad[i] = OPAD;\r
-        }\r
-        try {\r
-            md5 = MessageDigest.getInstance("MD5");\r
-        } catch (Exception ex) {\r
-            throw new IllegalStateException(ex.getMessage());\r
-        }\r
-        engineReset();\r
-    }\r
-\r
-    private HMACT64(HMACT64 hmac) throws CloneNotSupportedException {\r
-        super("HMACT64");\r
-        this.ipad = hmac.ipad;\r
-        this.opad = hmac.opad;\r
-        this.md5 = (MessageDigest) hmac.md5.clone();\r
-    }\r
-\r
-    public Object clone() {\r
-        try {\r
-            return new HMACT64(this);\r
-        } catch (CloneNotSupportedException ex) {\r
-            throw new IllegalStateException(ex.getMessage());\r
-        }\r
-    }\r
-\r
-    protected byte[] engineDigest() {\r
-        byte[] digest = md5.digest();\r
-        md5.update(opad);\r
-        return md5.digest(digest);\r
-    }\r
-\r
-    protected int engineDigest(byte[] buf, int offset, int len) {\r
-        byte[] digest = md5.digest();\r
-        md5.update(opad);\r
-        md5.update(digest);\r
-        try {\r
-            return md5.digest(buf, offset, len);\r
-        } catch (Exception ex) {\r
-            throw new IllegalStateException();\r
-        }\r
-    }\r
-\r
-    protected int engineGetDigestLength() {\r
-        return md5.getDigestLength();\r
-    }\r
-\r
-    protected void engineReset() {\r
-        md5.reset();\r
-        md5.update(ipad);\r
-    }\r
-\r
-    protected void engineUpdate(byte b) {\r
-        md5.update(b);\r
-    }\r
-\r
-    protected void engineUpdate(byte[] input, int offset, int len) {\r
-        md5.update(input, offset, len);\r
-    }\r
-\r
-}\r
diff --git a/update/NtlmHttpFilter.java b/update/NtlmHttpFilter.java
deleted file mode 100644 (file)
index d160e65..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/* jcifs smb client library in Java\r
- * Copyright (C) 2002  "Michael B. Allen" <jcifs at samba dot org>\r
- *                                      "Jason Pugsley" <jcifs at samba dot org>\r
- *                                      "skeetz" <jcifs at samba dot org>\r
- *                                      "Eric Glass" <jcifs at samba dot org>\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
- */\r
-\r
-package jcifs.http;\r
-\r
-import java.io.*;\r
-import java.util.Enumeration;\r
-import java.net.UnknownHostException;\r
-import javax.servlet.*;\r
-import javax.servlet.http.*;\r
-import jcifs.*;\r
-import jcifs.smb.SmbSession;\r
-import jcifs.smb.NtlmPasswordAuthentication;\r
-import jcifs.smb.SmbAuthException;\r
-import jcifs.util.Base64;\r
-\r
-/**\r
- * This servlet Filter can be used to negotiate password hashes with\r
- * MSIE clients using NTLM SSP. This is similar to <tt>Authentication:\r
- * BASIC</tt> but weakly encrypted and without requiring the user to re-supply\r
- * authentication credentials.\r
- * <p>\r
- * Read <a href="../../../ntlmhttpauth.html">jCIFS NTLM HTTP Authentication and the Network Explorer Servlet</a> for complete details.\r
- */\r
-\r
-public class NtlmHttpFilter implements Filter {\r
-\r
-    private String defaultDomain;\r
-\r
-       private String domainController;\r
-\r
-       private boolean enableBasic;\r
-\r
-       private boolean insecureBasic;\r
-\r
-       private String realm;\r
-\r
-       public void init( FilterConfig filterConfig ) throws ServletException {\r
-               String name;\r
-\r
-               /* Set jcifs properties we know we want; soTimeout and cachePolicy to 10min.\r
-                */\r
-               Config.setProperty( "jcifs.smb.client.soTimeout", "300000" );\r
-               Config.setProperty( "jcifs.netbios.cachePolicy", "600" );\r
-\r
-               Enumeration e = filterConfig.getInitParameterNames();\r
-               while( e.hasMoreElements() ) {\r
-                       name = (String)e.nextElement();\r
-                       if( name.startsWith( "jcifs." )) {\r
-                               Config.setProperty( name, filterConfig.getInitParameter( name ));\r
-                       }\r
-               }\r
-        defaultDomain = Config.getProperty("jcifs.smb.client.domain");\r
-               domainController = Config.getProperty( "jcifs.http.domainController" );\r
-               if( domainController == null ) domainController = defaultDomain;\r
-               enableBasic = Boolean.valueOf(\r
-                               Config.getProperty("jcifs.http.enableBasic")).booleanValue();\r
-               insecureBasic = Boolean.valueOf(\r
-                               Config.getProperty("jcifs.http.insecureBasic")).booleanValue();\r
-               realm = Config.getProperty("jcifs.http.basicRealm");\r
-               if (realm == null) realm = "jCIFS";\r
-       }\r
-       public void destroy() {\r
-       }\r
-       public void doFilter( ServletRequest request,\r
-                               ServletResponse response,\r
-                               FilterChain chain ) throws IOException, ServletException {\r
-               HttpServletRequest req;\r
-               HttpServletResponse resp;\r
-               UniAddress dc;\r
-               String msg;\r
-\r
-               NtlmPasswordAuthentication ntlm = null;\r
-               req = (HttpServletRequest)request;\r
-               resp = (HttpServletResponse)response;\r
-               msg = req.getHeader( "Authorization" );\r
-               boolean offerBasic = enableBasic && (insecureBasic || req.isSecure());\r
-\r
-               if( msg != null && (msg.startsWith( "NTLM " ) ||\r
-                                       (offerBasic && msg.startsWith("Basic ")))) {\r
-                       dc = UniAddress.getByName( domainController, true );\r
-                       if (msg.startsWith("NTLM ")) {\r
-                               byte[] challenge = SmbSession.getChallenge( dc );\r
-                               if(( ntlm = NtlmSsp.authenticate( req, resp, challenge )) == null ) {\r
-                                       return;\r
-                               }\r
-                       } else {\r
-                               String auth = new String(Base64.decode(msg.substring(6)),\r
-                                               "US-ASCII");\r
-                               int index = auth.indexOf(':');\r
-                               String user = (index != -1) ? auth.substring(0, index) : auth;\r
-                               String password = (index != -1) ? auth.substring(index + 1) :\r
-                                               "";\r
-                               index = user.indexOf('\\');\r
-                               if (index == -1) index = user.indexOf('/');\r
-                               String domain = (index != -1) ? user.substring(0, index) :\r
-                        defaultDomain;\r
-                               user = (index != -1) ? user.substring(index + 1) : user;\r
-                               ntlm = new NtlmPasswordAuthentication(domain, user, password);\r
-                       }\r
-                       try {\r
-                               SmbSession.logon( dc, ntlm );\r
-                       } catch( SmbAuthException sae ) {\r
-                               resp.setHeader( "WWW-Authenticate", "NTLM" );\r
-                               if (offerBasic) {\r
-                                       resp.addHeader( "WWW-Authenticate", "Basic realm=\"" +\r
-                                                       realm + "\"");\r
-                               }\r
-                               resp.setHeader( "Connection", "close" );\r
-                               resp.setStatus( HttpServletResponse.SC_UNAUTHORIZED );\r
-                               resp.flushBuffer();\r
-                               return;\r
-                       }\r
-                       req.getSession().setAttribute( "NtlmHttpAuth", ntlm );\r
-        } else {\r
-            HttpSession ssn = req.getSession(false);\r
-            if (ssn == null || (ntlm = (NtlmPasswordAuthentication)\r
-                    ssn.getAttribute("NtlmHttpAuth")) == null) {\r
-                resp.setHeader( "WWW-Authenticate", "NTLM" );\r
-                if (offerBasic) {\r
-                    resp.addHeader( "WWW-Authenticate", "Basic realm=\"" +\r
-                            realm + "\"");\r
-                }\r
-                resp.setHeader( "Connection", "close" );\r
-                resp.setStatus( HttpServletResponse.SC_UNAUTHORIZED );\r
-                resp.flushBuffer();\r
-                return;\r
-            }\r
-               }\r
-\r
-               chain.doFilter( new NtlmHttpServletRequest( req, ntlm ), response );\r
-       }\r
-\r
-       // Added by cgross to work with weblogic 6.1.\r
-       public void setFilterConfig( FilterConfig f ) {\r
-               try {\r
-                       init( f );\r
-               } catch( Exception e ) {\r
-                       e.printStackTrace();\r
-               }\r
-       }\r
-       public FilterConfig getFilterConfig() {\r
-               return null;\r
-       }\r
-}\r
-\r
diff --git a/update/NtlmHttpURLConnection.java b/update/NtlmHttpURLConnection.java
deleted file mode 100644 (file)
index 2af8f50..0000000
+++ /dev/null
@@ -1,563 +0,0 @@
-/* jcifs smb client library in Java\r
- * Copyright (C) 2002  "Michael B. Allen" <jcifs at samba dot org>\r
- *                                      "Eric Glass" <jcifs at samba dot org>\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
- */\r
-\r
-package jcifs.http;\r
-\r
-import java.io.InputStream;\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-\r
-import java.net.Authenticator;\r
-import java.net.HttpURLConnection;\r
-import java.net.PasswordAuthentication;\r
-import java.net.ProtocolException;\r
-import java.net.URL;\r
-import java.net.URLDecoder;\r
-\r
-import java.security.Permission;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Collections;\r
-import java.util.HashMap;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import java.util.Map;\r
-\r
-import jcifs.Config;\r
-\r
-import jcifs.ntlmssp.NtlmFlags;\r
-import jcifs.ntlmssp.NtlmMessage;\r
-import jcifs.ntlmssp.Type1Message;\r
-import jcifs.ntlmssp.Type2Message;\r
-import jcifs.ntlmssp.Type3Message;\r
-\r
-import jcifs.util.Base64;\r
-\r
-/**\r
- * Wraps an <code>HttpURLConnection</code> to provide NTLM authentication\r
- * services.\r
- *\r
- * Please read <a href="../../../httpclient.html">Using jCIFS NTLM Authentication for HTTP Connections</a>.\r
- */\r
-public class NtlmHttpURLConnection extends HttpURLConnection {\r
-\r
-    private static final int MAX_REDIRECTS =\r
-            Integer.parseInt(System.getProperty("http.maxRedirects", "20"));\r
-\r
-    private static final int LM_COMPATIBILITY =\r
-            Config.getInt("jcifs.smb.lmCompatibility", 0);\r
-\r
-    private static final String DEFAULT_DOMAIN;\r
-\r
-    private HttpURLConnection connection;\r
-\r
-    private Map requestProperties;\r
-\r
-    private Map headerFields;\r
-\r
-    private String authProperty;\r
-\r
-    private String method;\r
-\r
-    static {\r
-        String domain = System.getProperty("http.auth.ntlm.domain");\r
-        if (domain == null) domain = Type3Message.getDefaultDomain();\r
-        DEFAULT_DOMAIN = domain;\r
-    }\r
-\r
-    public NtlmHttpURLConnection(HttpURLConnection connection) {\r
-        super(connection.getURL());\r
-        this.connection = connection;\r
-        requestProperties = new HashMap();\r
-    }\r
-\r
-    public void connect() throws IOException {\r
-        if (connected) return;\r
-        doConnect();\r
-        connected = true;\r
-    }\r
-\r
-    public URL getURL() {\r
-        return connection.getURL();\r
-    }\r
-\r
-    public int getContentLength() {\r
-        try {\r
-            connect();\r
-        } catch (IOException ex) { }\r
-        return connection.getContentLength();\r
-    }\r
-\r
-    public String getContentType() {\r
-        try {\r
-            connect();\r
-        } catch (IOException ex) { }\r
-        return connection.getContentType();\r
-    }\r
-\r
-    public String getContentEncoding() {\r
-        try {\r
-            connect();\r
-        } catch (IOException ex) { }\r
-        return connection.getContentEncoding();\r
-    }\r
-\r
-    public long getExpiration() {\r
-        try {\r
-            connect();\r
-        } catch (IOException ex) { }\r
-        return connection.getExpiration();\r
-    }\r
-\r
-    public long getDate() {\r
-        try {\r
-            connect();\r
-        } catch (IOException ex) { }\r
-        return connection.getDate();\r
-    }\r
-\r
-    public long getLastModified() {\r
-        try {\r
-            connect();\r
-        } catch (IOException ex) { }\r
-        return connection.getLastModified();\r
-    }\r
-\r
-    public String getHeaderField(String header) {\r
-        try {\r
-            connect();\r
-        } catch (IOException ex) { }\r
-        return connection.getHeaderField(header);\r
-    }\r
-\r
-    private synchronized Map getHeaderFields0() {\r
-        if (headerFields != null) return headerFields;\r
-        Map map = new HashMap();\r
-        String key = connection.getHeaderFieldKey(0);\r
-        String value = connection.getHeaderField(0);\r
-        for (int i = 1; key != null || value != null; i++) {\r
-            List values = (List) map.get(key);\r
-            if (values == null) {\r
-                values = new ArrayList();\r
-                map.put(key, values);\r
-            }\r
-            values.add(value);\r
-            key = connection.getHeaderFieldKey(i);\r
-            value = connection.getHeaderField(i);\r
-        }\r
-        Iterator entries = map.entrySet().iterator();\r
-        while (entries.hasNext()) {\r
-            Map.Entry entry = (Map.Entry) entries.next();\r
-            entry.setValue(Collections.unmodifiableList((List)\r
-                    entry.getValue()));\r
-        }\r
-        return (headerFields = Collections.unmodifiableMap(map));\r
-    }\r
-\r
-    public Map getHeaderFields() {\r
-        synchronized (this) {\r
-            if (headerFields != null) return headerFields;\r
-        }\r
-        try {\r
-            connect();\r
-        } catch (IOException ex) { }\r
-        return getHeaderFields0();\r
-    }\r
-\r
-    public int getHeaderFieldInt(String header, int def) {\r
-        try {\r
-            connect();\r
-        } catch (IOException ex) { }\r
-        return connection.getHeaderFieldInt(header, def);\r
-    }\r
-\r
-    public long getHeaderFieldDate(String header, long def) {\r
-        try {\r
-            connect();\r
-        } catch (IOException ex) { }\r
-        return connection.getHeaderFieldDate(header, def);\r
-    }\r
-\r
-    public String getHeaderFieldKey(int index) {\r
-        try {\r
-            connect();\r
-        } catch (IOException ex) { }\r
-        return connection.getHeaderFieldKey(index);\r
-    }\r
-\r
-    public String getHeaderField(int index) {\r
-        try {\r
-            connect();\r
-        } catch (IOException ex) { }\r
-        return connection.getHeaderField(index);\r
-    }\r
-\r
-    public Object getContent() throws IOException {\r
-        try {\r
-            connect();\r
-        } catch (IOException ex) { }\r
-        return connection.getContent();\r
-    }\r
-\r
-    public Object getContent(Class[] classes) throws IOException {\r
-        try {\r
-            connect();\r
-        } catch (IOException ex) { }\r
-        return connection.getContent(classes);\r
-    }\r
-\r
-    public Permission getPermission() throws IOException {\r
-        return connection.getPermission();\r
-    }\r
-\r
-    public InputStream getInputStream() throws IOException {\r
-        try {\r
-            connect();\r
-        } catch (IOException ex) { }\r
-        return connection.getInputStream();\r
-    }\r
-\r
-    public OutputStream getOutputStream() throws IOException {\r
-        try {\r
-            connect();\r
-        } catch (IOException ex) { }\r
-        return connection.getOutputStream();\r
-    }\r
-\r
-    public String toString() {\r
-        return connection.toString();\r
-    }\r
-\r
-    public void setDoInput(boolean doInput) {\r
-        connection.setDoInput(doInput);\r
-        this.doInput = doInput;\r
-    }\r
-\r
-    public boolean getDoInput() {\r
-        return connection.getDoInput();\r
-    }\r
-\r
-    public void setDoOutput(boolean doOutput) {\r
-        connection.setDoOutput(doOutput);\r
-        this.doOutput = doOutput;\r
-    }\r
-\r
-    public boolean getDoOutput() {\r
-        return connection.getDoOutput();\r
-    }\r
-\r
-    public void setAllowUserInteraction(boolean allowUserInteraction) {\r
-        connection.setAllowUserInteraction(allowUserInteraction);\r
-        this.allowUserInteraction = allowUserInteraction;\r
-    }\r
-\r
-    public boolean getAllowUserInteraction() {\r
-        return connection.getAllowUserInteraction();\r
-    }\r
-\r
-    public void setUseCaches(boolean useCaches) {\r
-        connection.setUseCaches(useCaches);\r
-        this.useCaches = useCaches;\r
-    }\r
-\r
-    public boolean getUseCaches() {\r
-        return connection.getUseCaches();\r
-    }\r
-\r
-    public void setIfModifiedSince(long ifModifiedSince) {\r
-        connection.setIfModifiedSince(ifModifiedSince);\r
-        this.ifModifiedSince = ifModifiedSince;\r
-    }\r
-\r
-    public long getIfModifiedSince() {\r
-        return connection.getIfModifiedSince();\r
-    }\r
-\r
-    public boolean getDefaultUseCaches() {\r
-        return connection.getDefaultUseCaches();\r
-    }\r
-\r
-    public void setDefaultUseCaches(boolean defaultUseCaches) {\r
-        connection.setDefaultUseCaches(defaultUseCaches);\r
-    }\r
-\r
-    public void setRequestProperty(String key, String value) {\r
-        if (key == null) throw new NullPointerException();\r
-        List values = new ArrayList();\r
-        values.add(value);\r
-        boolean found = false;\r
-        synchronized (requestProperties) {\r
-            Iterator entries = requestProperties.entrySet().iterator();\r
-            while (entries.hasNext()) {\r
-                Map.Entry entry = (Map.Entry) entries.next();\r
-                if (key.equalsIgnoreCase((String) entry.getKey())) {\r
-                    entry.setValue(value);\r
-                    found = true;\r
-                    break;\r
-                }\r
-            }\r
-            if (!found) requestProperties.put(key, values);\r
-        }\r
-        connection.setRequestProperty(key, value);\r
-    }\r
-\r
-    public void addRequestProperty(String key, String value) {\r
-        if (key == null) throw new NullPointerException();\r
-        List values = null;\r
-        synchronized (requestProperties) {\r
-            Iterator entries = requestProperties.entrySet().iterator();\r
-            while (entries.hasNext()) {\r
-                Map.Entry entry = (Map.Entry) entries.next();\r
-                if (key.equalsIgnoreCase((String) entry.getKey())) {\r
-                    values = (List) entry.getValue();\r
-                    values.add(value);\r
-                    break;\r
-                }\r
-            }\r
-            if (values == null) {\r
-                values = new ArrayList();\r
-                values.add(value);\r
-                requestProperties.put(key, values);\r
-            }\r
-        }\r
-        // 1.3-compatible.\r
-        StringBuffer buffer = new StringBuffer();\r
-        Iterator propertyValues = values.iterator();\r
-        while (propertyValues.hasNext()) {\r
-            buffer.append(propertyValues.next());\r
-            if (propertyValues.hasNext()) {\r
-                buffer.append(", ");\r
-            }\r
-        }\r
-        connection.setRequestProperty(key, buffer.toString());\r
-    }\r
-\r
-    public String getRequestProperty(String key) {\r
-        return connection.getRequestProperty(key);\r
-    }\r
-\r
-    public Map getRequestProperties() {\r
-        Map map = new HashMap();\r
-        synchronized (requestProperties) {\r
-            Iterator entries = requestProperties.entrySet().iterator();\r
-            while (entries.hasNext()) {\r
-                Map.Entry entry = (Map.Entry) entries.next();\r
-                map.put(entry.getKey(),\r
-                        Collections.unmodifiableList((List) entry.getValue()));\r
-            }\r
-        }\r
-        return Collections.unmodifiableMap(map);\r
-    }\r
-\r
-    public void setInstanceFollowRedirects(boolean instanceFollowRedirects) {\r
-        connection.setInstanceFollowRedirects(instanceFollowRedirects);\r
-    }\r
-\r
-    public boolean getInstanceFollowRedirects() {\r
-        return connection.getInstanceFollowRedirects();\r
-    }\r
-\r
-    public void setRequestMethod(String requestMethod)\r
-            throws ProtocolException {\r
-        connection.setRequestMethod(requestMethod);\r
-    }\r
-\r
-    public String getRequestMethod() {\r
-        return connection.getRequestMethod();\r
-    }\r
-\r
-    public int getResponseCode() throws IOException {\r
-        return connection.getResponseCode();\r
-    }\r
-\r
-    public String getResponseMessage() throws IOException {\r
-        return connection.getResponseMessage();\r
-    }\r
-\r
-    public void disconnect() {\r
-        connection.disconnect();\r
-        connected = false;\r
-    }\r
-\r
-    public boolean usingProxy() {\r
-        return connection.usingProxy();\r
-    }\r
-\r
-    public InputStream getErrorStream() {\r
-        return connection.getErrorStream();\r
-    }\r
-\r
-    private int parseResponseCode() throws IOException {\r
-        try {\r
-            String response = connection.getHeaderField(0);\r
-            int index = response.indexOf(' ');\r
-            while (response.charAt(index) == ' ') index++;\r
-            return Integer.parseInt(response.substring(index, index + 3));\r
-        } catch (Exception ex) {\r
-            throw new IOException(ex.getMessage());\r
-        }\r
-    }\r
-\r
-    private synchronized void doConnect() throws IOException {\r
-        connection.connect();\r
-        int response = parseResponseCode();\r
-        if (response != HTTP_UNAUTHORIZED && response != HTTP_PROXY_AUTH) {\r
-            return;\r
-        }\r
-        Type1Message type1 = (Type1Message) attemptNegotiation(response);\r
-        if (type1 == null) return; // no NTLM\r
-        int attempt = 0;\r
-        while (attempt < MAX_REDIRECTS) {\r
-            connection.setRequestProperty(authProperty, method + ' ' +\r
-                    Base64.encode(type1.toByteArray()));\r
-            connection.connect(); // send type 1\r
-            response = parseResponseCode();\r
-            if (response != HTTP_UNAUTHORIZED && response != HTTP_PROXY_AUTH) {\r
-                return;\r
-            }\r
-            Type3Message type3 = (Type3Message) attemptNegotiation(response);\r
-            if (type3 == null) return;\r
-            connection.setRequestProperty(authProperty, method + ' ' +\r
-                    Base64.encode(type3.toByteArray()));\r
-            connection.connect(); // send type 3\r
-            response = parseResponseCode();\r
-            if (response != HTTP_UNAUTHORIZED && response != HTTP_PROXY_AUTH) {\r
-                return;\r
-            }\r
-            attempt++;\r
-            if (attempt < MAX_REDIRECTS) reconnect();\r
-        }\r
-        throw new IOException("Unable to negotiate NTLM authentication.");\r
-    }\r
-\r
-    private NtlmMessage attemptNegotiation(int response) throws IOException {\r
-        authProperty = null;\r
-        method = null;\r
-        InputStream errorStream = connection.getErrorStream();\r
-        if (errorStream != null && errorStream.available() != 0) {\r
-            int count;\r
-            byte[] buf = new byte[1024];\r
-            while ((count = errorStream.read(buf, 0, 1024)) != -1);\r
-        }\r
-        String authHeader;\r
-        if (response == HTTP_UNAUTHORIZED) {\r
-            authHeader = "WWW-Authenticate";\r
-            authProperty = "Authorization";\r
-        } else {\r
-            authHeader = "Proxy-Authenticate";\r
-            authProperty = "Proxy-Authorization";\r
-        }\r
-        String authorization = null;\r
-        List methods = (List) getHeaderFields0().get(authHeader);\r
-        if (methods == null) return null;\r
-        Iterator iterator = methods.iterator();\r
-        while (iterator.hasNext()) {\r
-            String authMethod = (String) iterator.next();\r
-            if (authMethod.startsWith("NTLM")) {\r
-                if (authMethod.length() == 4) {\r
-                    method = "NTLM";\r
-                    break;\r
-                }\r
-                if (authMethod.indexOf(' ') != 4) continue;\r
-                method = "NTLM";\r
-                authorization = authMethod.substring(5).trim();\r
-                break;\r
-            } else if (authMethod.startsWith("Negotiate")) {\r
-                if (authMethod.length() == 9) {\r
-                    method = "Negotiate";\r
-                    break;\r
-                }\r
-                if (authMethod.indexOf(' ') != 9) continue;\r
-                method = "Negotiate";\r
-                authorization = authMethod.substring(10).trim();\r
-                break;\r
-            }\r
-        }\r
-        if (method == null) return null;\r
-        NtlmMessage message = (authorization != null) ?\r
-                new Type2Message(Base64.decode(authorization)) : null;\r
-        reconnect();\r
-        if (message == null) {\r
-            message = new Type1Message();\r
-            if (LM_COMPATIBILITY > 2) {\r
-                message.setFlag(NtlmFlags.NTLMSSP_REQUEST_TARGET, true);\r
-            }\r
-        } else {\r
-            String domain = DEFAULT_DOMAIN;\r
-            String user = Type3Message.getDefaultUser();\r
-            String password = Type3Message.getDefaultPassword();\r
-            String userInfo = url.getUserInfo();\r
-            if (userInfo != null) {\r
-                userInfo = URLDecoder.decode(userInfo);\r
-                int index = userInfo.indexOf(':');\r
-                user = (index != -1) ? userInfo.substring(0, index) : userInfo;\r
-                if (index != -1) password = userInfo.substring(index + 1);\r
-                index = user.indexOf('\\');\r
-                if (index == -1) index = user.indexOf('/');\r
-                domain = (index != -1) ? user.substring(0, index) : domain;\r
-                user = (index != -1) ? user.substring(index + 1) : user;\r
-            }\r
-            if (user == null) {\r
-                try {\r
-                    URL url = getURL();\r
-                    String protocol = url.getProtocol();\r
-                    int port = url.getPort();\r
-                    if (port == -1) {\r
-                        port = "https".equalsIgnoreCase(protocol) ? 443 : 80;\r
-                    }\r
-                    PasswordAuthentication auth =\r
-                            Authenticator.requestPasswordAuthentication(null,\r
-                                    port, protocol, "", method);\r
-                    if (auth != null) {\r
-                        user = auth.getUserName();\r
-                        password = new String(auth.getPassword());\r
-                    }\r
-                } catch (Exception ex) { }\r
-            }\r
-            Type2Message type2 = (Type2Message) message;\r
-            message = new Type3Message(type2, password, domain, user,\r
-                    Type3Message.getDefaultWorkstation());\r
-        }\r
-        return message;\r
-    }\r
-\r
-    private void reconnect() throws IOException {\r
-        connection = (HttpURLConnection) connection.getURL().openConnection();\r
-        headerFields = null;\r
-        synchronized (requestProperties) {\r
-            Iterator properties = requestProperties.entrySet().iterator();\r
-            while (properties.hasNext()) {\r
-                Map.Entry property = (Map.Entry) properties.next();\r
-                String key = (String) property.getKey();\r
-                StringBuffer value = new StringBuffer();\r
-                Iterator values = ((List) property.getValue()).iterator();\r
-                while (values.hasNext()) {\r
-                    value.append(values.next());\r
-                    if (values.hasNext()) value.append(", ");\r
-                }\r
-                connection.setRequestProperty(key, value.toString());\r
-            }\r
-        }\r
-        connection.setAllowUserInteraction(allowUserInteraction);\r
-        connection.setDoInput(doInput);\r
-        connection.setDoOutput(doOutput);\r
-        connection.setIfModifiedSince(ifModifiedSince);\r
-        connection.setUseCaches(useCaches);\r
-    }\r
-}\r
diff --git a/update/NtlmMessage.java b/update/NtlmMessage.java
deleted file mode 100644 (file)
index 3b8c692..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/* jcifs smb client library in Java\r
- * Copyright (C) 2002  "Michael B. Allen" <jcifs at samba dot org>\r
- *                                      "Eric Glass" <jcifs at samba dot org>\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
- */\r
-\r
-package jcifs.ntlmssp;\r
-\r
-import jcifs.Config;\r
-\r
-/**\r
- * Abstract superclass for all NTLMSSP messages.\r
- */\r
-public abstract class NtlmMessage implements NtlmFlags {\r
-\r
-    /**\r
-     * The NTLMSSP "preamble".\r
-     */\r
-    protected static final byte[] NTLMSSP_SIGNATURE = new byte[] {\r
-        (byte) 'N', (byte) 'T', (byte) 'L', (byte) 'M',\r
-        (byte) 'S', (byte) 'S', (byte) 'P', (byte) 0\r
-    };\r
-\r
-    private static final String OEM_ENCODING =\r
-            Config.getProperty("jcifs.smb.client.codepage",\r
-                    Config.getProperty("jcifs.encoding",\r
-                            System.getProperty("file.encoding")));\r
-\r
-    private int flags;\r
-\r
-    /**\r
-     * Returns the flags currently in use for this message.\r
-     *\r
-     * @return An <code>int</code> containing the flags in use for this\r
-     * message.\r
-     */\r
-    public int getFlags() {\r
-        return flags;\r
-    }\r
-\r
-    /**\r
-     * Sets the flags for this message.\r
-     *\r
-     * @param flags The flags for this message.\r
-     */\r
-    public void setFlags(int flags) {\r
-        this.flags = flags;\r
-    }\r
-\r
-    /**\r
-     * Returns the status of the specified flag.\r
-     *\r
-     * @param flag The flag to test (i.e., <code>NTLMSSP_NEGOTIATE_OEM</code>).\r
-     * @return A <code>boolean</code> indicating whether the flag is set.\r
-     */\r
-    public boolean getFlag(int flag) {\r
-        return (getFlags() & flag) != 0;\r
-    }\r
-\r
-    /**\r
-     * Sets or clears the specified flag.\r
-     * \r
-     * @param flag The flag to set/clear (i.e.,\r
-     * <code>NTLMSSP_NEGOTIATE_OEM</code>).\r
-     * @param value Indicates whether to set (<code>true</code>) or\r
-     * clear (<code>false</code>) the specified flag.\r
-     */\r
-    public void setFlag(int flag, boolean value) {\r
-        setFlags(value ? (getFlags() | flag) :\r
-                (getFlags() & (0xffffffff ^ flag)));\r
-    }\r
-\r
-    static int readULong(byte[] src, int index) {\r
-        return (src[index] & 0xff) |\r
-                ((src[index + 1] & 0xff) << 8) |\r
-                ((src[index + 2] & 0xff) << 16) |\r
-                ((src[index + 3] & 0xff) << 24);\r
-    }\r
-\r
-    static int readUShort(byte[] src, int index) {\r
-        return (src[index] & 0xff) | ((src[index + 1] & 0xff) << 8);\r
-    }\r
-\r
-    static byte[] readSecurityBuffer(byte[] src, int index) {\r
-        int length = readUShort(src, index);\r
-        int offset = readULong(src, index + 4);\r
-        byte[] buffer = new byte[length];\r
-        System.arraycopy(src, offset, buffer, 0, length);\r
-        return buffer;\r
-    }\r
-\r
-    static void writeULong(byte[] dest, int offset, int ulong) {\r
-        dest[offset] = (byte) (ulong & 0xff);\r
-        dest[offset + 1] = (byte) (ulong >> 8 & 0xff);\r
-        dest[offset + 2] = (byte) (ulong >> 16 & 0xff);\r
-        dest[offset + 3] = (byte) (ulong >> 24 & 0xff);\r
-    }\r
-\r
-    static void writeUShort(byte[] dest, int offset, int ushort) {\r
-        dest[offset] = (byte) (ushort & 0xff);\r
-        dest[offset + 1] = (byte) (ushort >> 8 & 0xff);\r
-    }\r
-\r
-    static void writeSecurityBuffer(byte[] dest, int offset, int bodyOffset,\r
-            byte[] src) {\r
-        int length = (src != null) ? src.length : 0;\r
-        if (length == 0) return;\r
-        writeUShort(dest, offset, length);\r
-        writeUShort(dest, offset + 2, length);\r
-        writeULong(dest, offset + 4, bodyOffset);\r
-        System.arraycopy(src, 0, dest, bodyOffset, length);\r
-    }\r
-\r
-    static String getOEMEncoding() {\r
-        return OEM_ENCODING;\r
-    }\r
-\r
-    /**\r
-     * Returns the raw byte representation of this message.\r
-     *\r
-     * @return A <code>byte[]</code> containing the raw message material.\r
-     */\r
-    public abstract byte[] toByteArray();\r
-\r
-}\r
diff --git a/update/NtlmPasswordAuthentication.java b/update/NtlmPasswordAuthentication.java
deleted file mode 100644 (file)
index a180c0c..0000000
+++ /dev/null
@@ -1,348 +0,0 @@
-/* jcifs smb client library in Java\r
- * Copyright (C) 2002  "Michael B. Allen" <jcifs at samba dot org>\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
- */\r
-\r
-package jcifs.smb;\r
-\r
-import jcifs.util.DES;\r
-import jcifs.util.MD4;\r
-import jcifs.util.HMACT64;\r
-import java.io.UnsupportedEncodingException;\r
-import java.security.Principal;\r
-import java.security.SecureRandom;\r
-import java.util.Arrays;\r
-import jcifs.Config;\r
-\r
-/**\r
- * This class stores and encrypts NTLM user credentials. The default\r
- * credentials are retrieved from the <tt>jcifs.smb.client.domain</tt>,\r
- * <tt>jcifs.smb.client.username</tt>, and <tt>jcifs.smb.client.password</tt>\r
- * properties.\r
- * <p>\r
- * Read <a href="../../../authhandler.html">jCIFS Exceptions and\r
- * NtlmAuthenticator</a> for related information.\r
- */\r
-\r
-public final class NtlmPasswordAuthentication implements Principal {\r
-\r
-    private static final int LM_COMPATIBILITY =\r
-            Config.getInt("jcifs.smb.lmCompatibility", 0);\r
-\r
-    private static final String DEFAULT_DOMAIN =\r
-            Config.getProperty("jcifs.smb.client.domain", "?");\r
-\r
-    private static final String DEFAULT_USERNAME =\r
-            Config.getProperty("jcifs.smb.client.username", "GUEST");\r
-\r
-    private static final String DEFAULT_PASSWORD =\r
-            Config.getProperty("jcifs.smb.client.password", "");\r
-\r
-    private static final SecureRandom random = new SecureRandom();\r
-\r
-    // KGS!@#$%\r
-    static final byte[] S8 = {\r
-        (byte)0x4b, (byte)0x47, (byte)0x53, (byte)0x21,\r
-        (byte)0x40, (byte)0x23, (byte)0x24, (byte)0x25\r
-    };\r
-    static void E( byte[] key, byte[] data, byte[] e ) {\r
-        byte[] key7 = new byte[7];\r
-        byte[] e8 = new byte[8];\r
-\r
-        for( int i = 0; i < key.length / 7; i++ ) {\r
-            System.arraycopy( key, i * 7, key7, 0, 7 );\r
-            DES des = new DES( key7 );\r
-            des.encrypt( data, e8 );\r
-            System.arraycopy( e8, 0, e, i * 8, 8 );\r
-        }\r
-    }\r
-/**\r
- * Generate the ANSI DES hash for the password associated with these credentials.\r
- */\r
-    static public byte[] getPreNTLMResponse( String password, byte[] challenge ) {\r
-        byte[] p14 = new byte[14];\r
-        byte[] p21 = new byte[21];\r
-        byte[] p24 = new byte[24];\r
-        byte[] passwordBytes;\r
-        try {\r
-            passwordBytes = password.toUpperCase().getBytes( ServerMessageBlock.encoding );\r
-        } catch( UnsupportedEncodingException uee ) {\r
-            return null;\r
-        }\r
-        int passwordLength = passwordBytes.length;\r
-\r
-        // Only encrypt the first 14 bytes of the password for Pre 0.12 NT LM\r
-        if( passwordLength > 14) {\r
-            passwordLength = 14;\r
-        }\r
-        System.arraycopy( passwordBytes, 0, p14, 0, passwordLength );\r
-        E( p14, S8, p21);\r
-        E( p21, challenge, p24);\r
-        return p24;\r
-    }\r
-/**\r
- * Generate the Unicode MD4 hash for the password associated with these credentials.\r
- */\r
-    static public byte[] getNTLMResponse( String password, byte[] challenge ) {\r
-        byte[] uni = null;\r
-        byte[] p21 = new byte[21];\r
-        byte[] p24 = new byte[24];\r
-\r
-        try {\r
-            uni = password.getBytes( "UnicodeLittleUnmarked" );\r
-        } catch( UnsupportedEncodingException uee ) {\r
-            Log.printStackTrace( "password encryption exception", uee );\r
-        }\r
-        MD4 md4 = new MD4();\r
-        md4.update( uni );\r
-        try {\r
-            md4.digest(p21, 0, 16);\r
-        } catch (Exception ex) {\r
-            Log.printStackTrace( "digest exception", ex );\r
-        }\r
-        E( p21, challenge, p24 );\r
-        return p24;\r
-    }\r
-\r
-    /**\r
-     * Creates the LMv2 response for the supplied information.\r
-     *\r
-     * @param domain The domain in which the username exists.\r
-     * @param user The username.\r
-     * @param password The user's password.\r
-     * @param challenge The server challenge.\r
-     * @param clientChallenge The client challenge (nonce). \r
-     */ \r
-    public static byte[] getLMv2Response(String domain, String user,\r
-            String password, byte[] challenge, byte[] clientChallenge) {\r
-        try {\r
-            byte[] hash = new byte[16];\r
-            byte[] response = new byte[24];\r
-            MD4 md4 = new MD4();\r
-            md4.update(password.getBytes("UnicodeLittleUnmarked"));\r
-            HMACT64 hmac = new HMACT64(md4.digest());\r
-            hmac.update(user.toUpperCase().getBytes("UnicodeLittleUnmarked"));\r
-            hmac.update(domain.toUpperCase().getBytes("UnicodeLittleUnmarked"));\r
-            hmac = new HMACT64(hmac.digest());\r
-            hmac.update(challenge);\r
-            hmac.update(clientChallenge);\r
-            hmac.digest(response, 0, 16);\r
-            System.arraycopy(clientChallenge, 0, response, 16, 8);\r
-            return response;\r
-        } catch (Exception ex) {\r
-            Log.printStackTrace("Error creating LMv2 response", ex);\r
-            return null;\r
-        }\r
-    }\r
-\r
-    static final NtlmPasswordAuthentication NULL =\r
-                new NtlmPasswordAuthentication( "", "", "" );\r
-    static final NtlmPasswordAuthentication GUEST =\r
-                new NtlmPasswordAuthentication( "?", "GUEST", "" );\r
-\r
-    String domain;\r
-    String username;\r
-    String password;\r
-    byte[] ansiHash;\r
-    byte[] unicodeHash;\r
-    boolean hashesExternal = false;\r
-\r
-/**\r
- * Create an <tt>NtlmPasswordAuthentication</tt> object from the userinfo\r
- * component of an SMB URL like "<tt>domain;user:pass</tt>". This constructor\r
- * is used internally be jCIFS when parsing SMB URLs.\r
- */\r
-\r
-    public NtlmPasswordAuthentication( String userInfo ) {\r
-        domain = username = password = null;\r
-\r
-        if( userInfo != null ) {\r
-            int i, u, end;\r
-            char c;\r
-\r
-            end = userInfo.length();\r
-            for( i = 0, u = 0; i < end; i++ ) {\r
-                c = userInfo.charAt( i );\r
-                if( c == ';' ) {\r
-                    domain = userInfo.substring( 0, i );\r
-                    u = i + 1;\r
-                } else if( c == ':' ) {\r
-                    password = userInfo.substring( i + 1 );\r
-                    break;\r
-                }\r
-            }\r
-            username = userInfo.substring( u, i );\r
-        }\r
-\r
-        if( domain == null ) this.domain = DEFAULT_DOMAIN;\r
-        if( username == null ) this.username = DEFAULT_USERNAME;\r
-        if( password == null ) this.password = DEFAULT_PASSWORD;\r
-    }\r
-/**\r
- * Create an <tt>NtlmPasswordAuthentication</tt> object from a\r
- * domain, username, and password. Parameters that are <tt>null</tt>\r
- * will be substituted with <tt>jcifs.smb.client.domain</tt>,\r
- * <tt>jcifs.smb.client.username</tt>, <tt>jcifs.smb.client.password</tt>\r
- * property values.\r
- */\r
-    public NtlmPasswordAuthentication( String domain, String username, String password ) {\r
-        this.domain = domain;\r
-        this.username = username;\r
-        this.password = password;\r
-        if( domain == null ) this.domain = DEFAULT_DOMAIN;\r
-        if( username == null ) this.username = DEFAULT_USERNAME;\r
-        if( password == null ) this.password = DEFAULT_PASSWORD;\r
-    }\r
-/**\r
- * Create an <tt>NtlmPasswordAuthentication</tt> object with raw password\r
- * hashes. This is used exclusively by the <tt>jcifs.http.NtlmSsp</tt>\r
- * class which is in turn used by NTLM HTTP authentication functionality.\r
- */\r
-    public NtlmPasswordAuthentication( String domain, String username,\r
-                                    byte[] ansiHash, byte[] unicodeHash ) {\r
-        if( domain == null || username == null ||\r
-                                    ansiHash == null || unicodeHash == null ) {\r
-            throw new IllegalArgumentException( "External credentials cannot null" );\r
-        }\r
-        this.domain = domain;\r
-        this.username = username;\r
-        this.password = null;\r
-        this.ansiHash = ansiHash;\r
-        this.unicodeHash = unicodeHash;\r
-        hashesExternal = true;\r
-    }\r
-\r
-/**\r
- * Returns the domain.\r
- */\r
-    public String getDomain() {\r
-        return domain;\r
-    }\r
-/**\r
- * Returns the username.\r
- */\r
-    public String getUsername() {\r
-        return username;\r
-    }\r
-/**\r
- * Returns the password in plain text or <tt>null</tt> if the raw password\r
- * hashes were used to construct this <tt>NtlmPasswordAuthentication</tt>\r
- * object which will be the case when NTLM HTTP Authentication is\r
- * used. There is no way to retrieve a users password in plain text unless\r
- * it is supplied by the user at runtime.\r
- */\r
-    public String getPassword() {\r
-        return password;\r
-    }\r
-/**\r
- * Return the domain and username in the format:\r
- * <tt>domain\\username</tt>. This is equivalent to <tt>toString()</tt>.\r
- */\r
-    public String getName() {\r
-        boolean d = domain.length() > 0 && domain.equals( "?" ) == false;\r
-        return d ? domain + "\\" + username : username;\r
-    }\r
-/**\r
- * Computes the 24 byte ANSI password hash given the 8 byte server challenge.\r
- */\r
-    public byte[] getAnsiHash( byte[] challenge ) {\r
-        if( hashesExternal ) {\r
-            return ansiHash;\r
-        }\r
-        switch (LM_COMPATIBILITY) {\r
-        case 0:\r
-        case 1:\r
-            return getPreNTLMResponse( password, challenge );\r
-        case 2:\r
-            return getNTLMResponse( password, challenge );\r
-        case 3:\r
-        case 4:\r
-        case 5:\r
-            byte[] clientChallenge = new byte[8];\r
-            random.nextBytes(clientChallenge);\r
-            return getLMv2Response(domain, username, password, challenge,\r
-                    clientChallenge);\r
-        default:\r
-            return getPreNTLMResponse( password, challenge );\r
-        }\r
-    }\r
-/**\r
- * Computes the 24 byte Unicode password hash given the 8 byte server challenge.\r
- */\r
-    public byte[] getUnicodeHash( byte[] challenge ) {\r
-        if( hashesExternal ) {\r
-            return unicodeHash;\r
-        }\r
-        switch (LM_COMPATIBILITY) {\r
-        case 0:\r
-        case 1:\r
-        case 2:\r
-            return getNTLMResponse( password, challenge );\r
-        case 3:\r
-        case 4:\r
-        case 5:\r
-            /*\r
-            byte[] clientChallenge = new byte[8];\r
-            random.nextBytes(clientChallenge);\r
-            return getNTLMv2Response(domain, username, password, null,\r
-                    challenge, clientChallenge);\r
-            */\r
-            return new byte[0];\r
-        default:\r
-            return getNTLMResponse( password, challenge );\r
-        }\r
-    }\r
-/**\r
- * Compares two <tt>NtlmPasswordAuthentication</tt> objects for\r
- * equality. Two <tt>NtlmPasswordAuthentication</tt> objects are equal if\r
- * 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.\r
- */\r
-    public boolean equals( Object obj ) {\r
-        if( obj instanceof NtlmPasswordAuthentication ) {\r
-            NtlmPasswordAuthentication ntlm = (NtlmPasswordAuthentication)obj;\r
-            if( ntlm.domain.toUpperCase().equals( domain.toUpperCase() ) &&\r
-                        ntlm.username.toUpperCase().equals( username.toUpperCase() )) {\r
-                if( hashesExternal && ntlm.hashesExternal ) {\r
-                    return Arrays.equals( ansiHash, ntlm.ansiHash ) &&\r
-                                Arrays.equals( unicodeHash, ntlm.unicodeHash );\r
-                    /* This still isn't quite right. If one npa object does not have external\r
-                     * hashes and the other does then they will not be considered equal even\r
-                     * though they may be.\r
-                     */\r
-                } else if( !hashesExternal && password.equals( ntlm.password )) {\r
-                    return true;\r
-                }\r
-            }\r
-        }\r
-        return false;\r
-    }\r
-\r
-\r
-/**\r
- * Return the upcased username hash code.\r
- */\r
-    public int hashCode() {\r
-        return getName().toUpperCase().hashCode();\r
-    }\r
-/**\r
- * Return the domain and username in the format:\r
- * <tt>domain\\username</tt>. This is equivalent to <tt>getName()</tt>.\r
- */\r
-    public String toString() {\r
-        return getName();\r
-    }\r
-}\r
-\r
diff --git a/update/NtlmServlet.java b/update/NtlmServlet.java
deleted file mode 100644 (file)
index 1304051..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/* jcifs smb client library in Java\r
- * Copyright (C) 2002  "Michael B. Allen" <jcifs at samba dot org>\r
- *                                      "Eric Glass" <jcifs at samba dot org>\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
- */\r
-\r
-package jcifs.http;\r
-\r
-import java.io.IOException;\r
-\r
-import java.net.UnknownHostException;\r
-\r
-import java.util.Enumeration;\r
-\r
-import javax.servlet.ServletConfig;\r
-import javax.servlet.ServletException;\r
-import javax.servlet.UnavailableException;\r
-\r
-import javax.servlet.http.HttpSession;\r
-import javax.servlet.http.HttpServlet;\r
-import javax.servlet.http.HttpServletRequest;\r
-import javax.servlet.http.HttpServletResponse;\r
-\r
-import jcifs.Config;\r
-import jcifs.UniAddress;\r
-\r
-import jcifs.smb.NtlmPasswordAuthentication;\r
-import jcifs.smb.SmbAuthException;\r
-import jcifs.smb.SmbSession;\r
-\r
-import jcifs.util.Base64;\r
-\r
-/**\r
- * This servlet may be used with pre-2.3 servlet containers\r
- * to protect content with NTLM HTTP Authentication. Servlets that\r
- * extend this abstract base class may be authenticatied against an SMB\r
- * server or domain controller depending on how the\r
- * <tt>jcifs.smb.client.domain</tt> or <tt>jcifs.http.domainController</tt>\r
- * properties are be specified. <b>With later containers the\r
- * <tt>NtlmHttpFilter</tt> should be used/b>. For custom NTLM HTTP Authentication schemes the <tt>NtlmSsp</tt> may be used.\r
- * <p>\r
- * Read <a href="../../../ntlmhttpauth.html">jCIFS NTLM HTTP Authentication and the Network Explorer Servlet</a> related information.\r
- */\r
-\r
-public abstract class NtlmServlet extends HttpServlet {\r
-\r
-    private String defaultDomain;\r
-\r
-       private String domainController;\r
-\r
-       private boolean enableBasic;\r
-\r
-       private boolean insecureBasic;\r
-\r
-       private String realm;\r
-\r
-       public void init(ServletConfig config) throws ServletException {\r
-               super.init(config);\r
-\r
-               /* Set jcifs properties we know we want; soTimeout and cachePolicy to 10min.\r
-                */\r
-               Config.setProperty( "jcifs.smb.client.soTimeout", "300000" );\r
-               Config.setProperty( "jcifs.netbios.cachePolicy", "600" );\r
-\r
-               Enumeration e = config.getInitParameterNames();\r
-               String name;\r
-               while (e.hasMoreElements()) {\r
-                       name = (String) e.nextElement();\r
-                       if (name.startsWith("jcifs.")) {\r
-                               Config.setProperty(name, config.getInitParameter(name));\r
-                       }\r
-               }\r
-        defaultDomain = Config.getProperty("jcifs.smb.client.domain");\r
-               domainController = Config.getProperty("jcifs.http.domainController");\r
-               if (domainController == null) domainController = defaultDomain;\r
-               enableBasic = Boolean.valueOf(\r
-                               Config.getProperty("jcifs.http.enableBasic")).booleanValue();\r
-               insecureBasic = Boolean.valueOf(\r
-                               Config.getProperty("jcifs.http.insecureBasic")).booleanValue();\r
-               realm = Config.getProperty("jcifs.http.basicRealm");\r
-               if (realm == null) realm = "jCIFS";\r
-       }\r
-\r
-       protected void service(HttpServletRequest request,\r
-                       HttpServletResponse response) throws ServletException, IOException {\r
-               boolean offerBasic = enableBasic &&\r
-                               (insecureBasic || request.isSecure());\r
-               String msg = request.getHeader("Authorization");\r
-               if (msg != null && (msg.startsWith("NTLM ") ||\r
-                                       (offerBasic && msg.startsWith("Basic ")))) {\r
-            UniAddress dc = UniAddress.getByName(domainController, true);\r
-                       NtlmPasswordAuthentication ntlm;\r
-                       if (msg.startsWith("NTLM ")) {\r
-                               byte[] challenge = SmbSession.getChallenge(dc);\r
-                               ntlm = NtlmSsp.authenticate(request, response, challenge);\r
-                               if (ntlm == null) return;\r
-                       } else {\r
-                               String auth = new String(Base64.decode(msg.substring(6)),\r
-                                               "US-ASCII");\r
-                               int index = auth.indexOf(':');\r
-                               String user = (index != -1) ? auth.substring(0, index) : auth;\r
-                               String password = (index != -1) ? auth.substring(index + 1) :\r
-                                               "";\r
-                               index = user.indexOf('\\');\r
-                               if (index == -1) index = user.indexOf('/');\r
-                               String domain = (index != -1) ? user.substring(0, index) :\r
-                                               defaultDomain;\r
-                               user = (index != -1) ? user.substring(index + 1) : user;\r
-                               ntlm = new NtlmPasswordAuthentication(domain, user, password);\r
-                       }\r
-                       try {\r
-                               SmbSession.logon(dc, ntlm);\r
-                       } catch (SmbAuthException sae) {\r
-                               response.setHeader("WWW-Authenticate", "NTLM");\r
-                               if (offerBasic) {\r
-                                       response.addHeader("WWW-Authenticate", "Basic realm=\"" +\r
-                                                       realm + "\"");\r
-                               }\r
-                               response.setHeader("Connection", "close");\r
-                               response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);\r
-                               response.flushBuffer();\r
-                               return;\r
-                       }\r
-                       HttpSession ssn = request.getSession();\r
-                       ssn.setAttribute("NtlmHttpAuth", ntlm);\r
-                       ssn.setAttribute( "ntlmdomain", ntlm.getDomain() );\r
-                       ssn.setAttribute( "ntlmuser", ntlm.getUsername() );\r
-        } else {\r
-            HttpSession ssn = request.getSession(false);\r
-            if (ssn == null || ssn.getAttribute("NtlmHttpAuth") == null) {\r
-                response.setHeader("WWW-Authenticate", "NTLM");\r
-                if (offerBasic) {\r
-                    response.addHeader("WWW-Authenticate", "Basic realm=\"" +\r
-                            realm + "\"");\r
-                }\r
-                response.setHeader("Connection", "close");\r
-                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);\r
-                response.flushBuffer();\r
-                return;\r
-            }\r
-               }\r
-               super.service(request, response);\r
-       }\r
-}\r
-\r
diff --git a/update/NtlmSsp.java b/update/NtlmSsp.java
deleted file mode 100644 (file)
index f781f1c..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/* jcifs smb client library in Java\r
- * Copyright (C) 2002  "Michael B. Allen" <jcifs at samba dot org>\r
- *                                      "Eric Glass" <jcifs at samba dot org>\r
- *                                      "Jason Pugsley" <jcifs at samba dot org>\r
- *                                      "skeetz" <jcifs at samba dot org>\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
- */\r
-\r
-package jcifs.http;\r
-\r
-import java.io.IOException;\r
-\r
-import javax.servlet.ServletException;\r
-\r
-import javax.servlet.http.HttpServletRequest;\r
-import javax.servlet.http.HttpServletResponse;\r
-\r
-import jcifs.smb.NtlmPasswordAuthentication;\r
-\r
-import jcifs.util.Base64;\r
-\r
-import jcifs.ntlmssp.NtlmFlags;\r
-import jcifs.ntlmssp.Type1Message;\r
-import jcifs.ntlmssp.Type2Message;\r
-import jcifs.ntlmssp.Type3Message;\r
-\r
-/**\r
- * This class is used internally by <tt>NtlmHttpFilter</tt>,\r
- * <tt>NtlmServlet</tt>, and <tt>NetworkExplorer</tt> to negiotiate password\r
- * hashes via NTLM SSP with MSIE. It might also be used directly by servlet\r
- * containers to incorporate similar functionality.\r
- * <p>\r
- * How NTLMSSP is used in conjunction with HTTP and MSIE clients is\r
- * described in an <A HREF="http://www.innovation.ch/java/ntlm.html">NTLM\r
- * Authentication Scheme for HTTP</A>.  <p> Also, read <a\r
- * href="../../../ntlmhttpauth.html">jCIFS NTLM HTTP Authentication and\r
- * the Network Explorer Servlet</a> related information.\r
- */\r
-\r
-public class NtlmSsp implements NtlmFlags {\r
-\r
-       /**\r
-        * Calls the static {@link #authenticate(HttpServletRequest,\r
-     * HttpServletResponse, byte[])} method to perform NTLM authentication\r
-     * for the specified servlet request.\r
-        *\r
-        * @param req The request being serviced.\r
-        * @param resp The response.\r
-        * @param challenge The domain controller challenge.\r
-        * @throws IOException If an IO error occurs.\r
-        * @throws ServletException If an error occurs.\r
-        */\r
-       public NtlmPasswordAuthentication doAuthentication(\r
-            HttpServletRequest req, HttpServletResponse resp, byte[] challenge)\r
-                                       throws IOException, ServletException {\r
-        return authenticate(req, resp, challenge);\r
-    }\r
-\r
-       /**\r
-        * Performs NTLM authentication for the servlet request.\r
-        *\r
-        * @param req The request being serviced.\r
-        * @param resp The response.\r
-        * @param challenge The domain controller challenge.\r
-        * @throws IOException If an IO error occurs.\r
-        * @throws ServletException If an error occurs.\r
-        */\r
-       public static NtlmPasswordAuthentication authenticate(\r
-            HttpServletRequest req, HttpServletResponse resp, byte[] challenge)\r
-                                       throws IOException, ServletException {\r
-               String msg = req.getHeader("Authorization");\r
-               if (msg != null && msg.startsWith("NTLM ")) {\r
-                       byte[] src = Base64.decode(msg.substring(5));\r
-                       if (src[8] == 1) {\r
-                               Type1Message type1 = new Type1Message(src);\r
-                               Type2Message type2 = new Type2Message(type1, challenge, null);\r
-                               msg = Base64.encode(type2.toByteArray());\r
-                               resp.setHeader( "WWW-Authenticate", "NTLM " + msg );\r
-                       } else if (src[8] == 3) {\r
-                               Type3Message type3 = new Type3Message(src);\r
-                               byte[] lmResponse = type3.getLMResponse();\r
-                               if (lmResponse == null) lmResponse = new byte[0];\r
-                               byte[] ntResponse = type3.getNTResponse();\r
-                               if (ntResponse == null) ntResponse = new byte[0];\r
-                               return new NtlmPasswordAuthentication(type3.getDomain(),\r
-                                               type3.getUser(), lmResponse, ntResponse);\r
-                       }\r
-               } else {\r
-                       resp.setHeader("WWW-Authenticate", "NTLM");\r
-                       resp.setHeader("Connection", "close");\r
-               }\r
-               resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);\r
-               resp.setContentLength( 0 );\r
-               resp.flushBuffer();\r
-               return null;\r
-       }\r
-\r
-}\r
-\r
diff --git a/update/Type1Message.java b/update/Type1Message.java
deleted file mode 100644 (file)
index ce31ec2..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
-/* jcifs smb client library in Java\r
- * Copyright (C) 2002  "Michael B. Allen" <jcifs at samba dot org>\r
- *                                      "Eric Glass" <jcifs at samba dot org>\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
- */\r
-\r
-package jcifs.ntlmssp;\r
-\r
-import java.io.IOException;\r
-\r
-import java.net.UnknownHostException;\r
-\r
-import jcifs.netbios.NbtAddress;\r
-\r
-import jcifs.Config;\r
-\r
-/**\r
- * Represents an NTLMSSP Type-1 message.\r
- */\r
-public class Type1Message extends NtlmMessage {\r
-\r
-    private static final int DEFAULT_FLAGS;\r
-\r
-    private static final String DEFAULT_DOMAIN;\r
-\r
-    private static final String DEFAULT_WORKSTATION;\r
-\r
-    private String suppliedDomain;\r
-\r
-    private String suppliedWorkstation;\r
-\r
-    static {\r
-        DEFAULT_FLAGS = NTLMSSP_NEGOTIATE_NTLM |\r
-                (Config.getBoolean("jcifs.smb.client.useUnicode", true) ?\r
-                        NTLMSSP_NEGOTIATE_UNICODE : NTLMSSP_NEGOTIATE_OEM);\r
-        DEFAULT_DOMAIN = Config.getProperty("jcifs.smb.client.domain", null);\r
-        String defaultWorkstation = null;\r
-        try {\r
-            defaultWorkstation = NbtAddress.getLocalHost().getHostName();\r
-        } catch (UnknownHostException ex) { }\r
-        DEFAULT_WORKSTATION = defaultWorkstation;\r
-    }\r
-\r
-    /**\r
-     * Creates a Type-1 message using default values from the current\r
-     * environment.\r
-     */\r
-    public Type1Message() {\r
-        this(getDefaultFlags(), getDefaultDomain(), getDefaultWorkstation());\r
-    }\r
-\r
-    /**\r
-     * Creates a Type-1 message with the specified parameters.\r
-     *\r
-     * @param flags The flags to apply to this message.\r
-     * @param suppliedDomain The supplied authentication domain.\r
-     * @param suppliedWorkstation The supplied workstation name.\r
-     */\r
-    public Type1Message(int flags, String suppliedDomain,\r
-            String suppliedWorkstation) {\r
-        setFlags(flags);\r
-        setSuppliedDomain(suppliedDomain);\r
-        setSuppliedWorkstation(suppliedWorkstation);\r
-    }\r
-\r
-    /**\r
-     * Creates a Type-1 message using the given raw Type-1 material.\r
-     *\r
-     * @param material The raw Type-1 material used to construct this message.\r
-     * @throws IOException If an error occurs while parsing the material.\r
-     */\r
-    public Type1Message(byte[] material) throws IOException {\r
-        parse(material);\r
-    }\r
-\r
-    /**\r
-     * Returns the supplied authentication domain.\r
-     *\r
-     * @return A <code>String</code> containing the supplied domain.\r
-     */\r
-    public String getSuppliedDomain() {\r
-        return suppliedDomain;\r
-    }\r
-\r
-    /**\r
-     * Sets the supplied authentication domain for this message.\r
-     *\r
-     * @param suppliedDomain The supplied domain for this message.\r
-     */\r
-    public void setSuppliedDomain(String suppliedDomain) {\r
-        this.suppliedDomain = suppliedDomain;\r
-    }\r
-\r
-    /**\r
-     * Returns the supplied workstation name.\r
-     * \r
-     * @return A <code>String</code> containing the supplied workstation name.\r
-     */\r
-    public String getSuppliedWorkstation() {\r
-        return suppliedWorkstation;\r
-    }\r
-\r
-    /**\r
-     * Sets the supplied workstation name for this message.\r
-     * \r
-     * @param suppliedWorkstation The supplied workstation for this message.\r
-     */\r
-    public void setSuppliedWorkstation(String suppliedWorkstation) {\r
-        this.suppliedWorkstation = suppliedWorkstation;\r
-    }\r
-\r
-    public byte[] toByteArray() {\r
-        try {\r
-            String suppliedDomain = getSuppliedDomain();\r
-            String suppliedWorkstation = getSuppliedWorkstation();\r
-            int flags = getFlags();\r
-            boolean hostInfo = false;\r
-            byte[] domain = new byte[0];\r
-            if (suppliedDomain != null && suppliedDomain.length() != 0) {\r
-                hostInfo = true;\r
-                flags |= NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED;\r
-                domain = suppliedDomain.toUpperCase().getBytes(\r
-                        getOEMEncoding());\r
-            } else {\r
-                flags &= (NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED ^ 0xffffffff);\r
-            }\r
-            byte[] workstation = new byte[0];\r
-            if (suppliedWorkstation != null &&\r
-                    suppliedWorkstation.length() != 0) {\r
-                hostInfo = true;\r
-                flags |= NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED;\r
-                workstation =\r
-                        suppliedWorkstation.toUpperCase().getBytes(\r
-                                getOEMEncoding());\r
-            } else {\r
-                flags &= (NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED ^\r
-                        0xffffffff);\r
-            }\r
-            byte[] type1 = new byte[hostInfo ?\r
-                    (32 + domain.length + workstation.length) : 16];\r
-            System.arraycopy(NTLMSSP_SIGNATURE, 0, type1, 0, 8);\r
-            writeULong(type1, 8, 1);\r
-            writeULong(type1, 12, flags);\r
-            if (hostInfo) {\r
-                writeSecurityBuffer(type1, 16, 32, domain);\r
-                writeSecurityBuffer(type1, 24, 32 + domain.length, workstation);\r
-            }\r
-            return type1;\r
-        } catch (IOException ex) {\r
-            throw new IllegalStateException(ex.getMessage());\r
-        }\r
-    }\r
-\r
-    public String toString() {\r
-        String suppliedDomain = getSuppliedDomain();\r
-        String suppliedWorkstation = getSuppliedWorkstation();\r
-        int flags = getFlags();\r
-        StringBuffer buffer = new StringBuffer();\r
-        if (suppliedDomain != null) {\r
-            buffer.append("suppliedDomain: ").append(suppliedDomain);\r
-        }\r
-        if (suppliedWorkstation != null) {\r
-            if (buffer.length() > 0) buffer.append("; ");\r
-            buffer.append("suppliedWorkstation: ").append(suppliedWorkstation);\r
-        }\r
-        if (flags != 0) {\r
-            if (buffer.length() > 0) buffer.append("; ");\r
-            buffer.append("flags: ");\r
-            buffer.append("0x");\r
-            buffer.append(Integer.toHexString((flags >> 28) & 0x0f));\r
-            buffer.append(Integer.toHexString((flags >> 24) & 0x0f));\r
-            buffer.append(Integer.toHexString((flags >> 20) & 0x0f));\r
-            buffer.append(Integer.toHexString((flags >> 16) & 0x0f));\r
-            buffer.append(Integer.toHexString((flags >> 12) & 0x0f));\r
-            buffer.append(Integer.toHexString((flags >> 8) & 0x0f));\r
-            buffer.append(Integer.toHexString((flags >> 4) & 0x0f));\r
-            buffer.append(Integer.toHexString(flags & 0x0f));\r
-        }\r
-        return buffer.toString();\r
-    }\r
-\r
-    /**\r
-     * Returns the default flags for a generic Type-1 message in the\r
-     * current environment.\r
-     * \r
-     * @return An <code>int</code> containing the default flags.\r
-     */\r
-    public static int getDefaultFlags() {\r
-        return DEFAULT_FLAGS;\r
-    }\r
-\r
-    /**\r
-     * Returns the default domain from the current environment.\r
-     *\r
-     * @return A <code>String</code> containing the default domain.\r
-     */\r
-    public static String getDefaultDomain() {\r
-        return DEFAULT_DOMAIN;\r
-    }\r
-\r
-    /**\r
-     * Returns the default workstation from the current environment.\r
-     *\r
-     * @return A <code>String</code> containing the default workstation.\r
-     */\r
-    public static String getDefaultWorkstation() {\r
-        return DEFAULT_WORKSTATION;\r
-    }\r
-\r
-    private void parse(byte[] material) throws IOException {\r
-        for (int i = 0; i < 8; i++) {\r
-            if (material[i] != NTLMSSP_SIGNATURE[i]) {\r
-                throw new IOException("Not an NTLMSSP message.");\r
-            }\r
-        }\r
-        if (readULong(material, 8) != 1) {\r
-            throw new IOException("Not a Type 1 message.");\r
-        }\r
-        int flags = readULong(material, 12);\r
-        String suppliedDomain = null;\r
-        if ((flags & NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED) != 0) {\r
-            byte[] domain = readSecurityBuffer(material, 16);\r
-            suppliedDomain = new String(domain, getOEMEncoding());\r
-        }\r
-        String suppliedWorkstation = null;\r
-        if ((flags & NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED) != 0) {\r
-            byte[] workstation = readSecurityBuffer(material, 24);\r
-            suppliedWorkstation = new String(workstation, getOEMEncoding());\r
-        }\r
-        setFlags(flags);\r
-        setSuppliedDomain(suppliedDomain);\r
-        setSuppliedWorkstation(suppliedWorkstation);\r
-    }\r
-\r
-}\r
diff --git a/update/Type2Message.java b/update/Type2Message.java
deleted file mode 100644 (file)
index a27db1f..0000000
+++ /dev/null
@@ -1,414 +0,0 @@
-/* jcifs smb client library in Java\r
- * Copyright (C) 2002  "Michael B. Allen" <jcifs at samba dot org>\r
- *                   "Eric Glass" <jcifs at samba dot org>\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
- */\r
-\r
-package jcifs.ntlmssp;\r
-\r
-import java.io.IOException;\r
-\r
-import java.net.UnknownHostException;\r
-\r
-import jcifs.Config;\r
-\r
-import jcifs.netbios.NbtAddress;\r
-\r
-/**\r
- * Represents an NTLMSSP Type-2 message.\r
- */\r
-public class Type2Message extends NtlmMessage {\r
-\r
-    private static final int DEFAULT_FLAGS;\r
-\r
-    private static final String DEFAULT_DOMAIN;\r
-\r
-    private static final byte[] DEFAULT_TARGET_INFORMATION;\r
-\r
-    private byte[] challenge;\r
-\r
-    private String target;\r
-\r
-    private byte[] context;\r
-\r
-    private byte[] targetInformation;\r
-\r
-    static {\r
-        DEFAULT_FLAGS = NTLMSSP_NEGOTIATE_NTLM |\r
-                (Config.getBoolean("jcifs.smb.client.useUnicode", true) ?\r
-                        NTLMSSP_NEGOTIATE_UNICODE : NTLMSSP_NEGOTIATE_OEM);\r
-        DEFAULT_DOMAIN = Config.getProperty("jcifs.smb.client.domain", null);\r
-        byte[] domain = new byte[0];\r
-        if (DEFAULT_DOMAIN != null) {\r
-            try {\r
-                domain = DEFAULT_DOMAIN.getBytes("UnicodeLittleUnmarked");\r
-            } catch (IOException ex) { }\r
-        }\r
-        int domainLength = domain.length;\r
-        byte[] server = new byte[0];\r
-        try {\r
-            String host = NbtAddress.getLocalHost().getHostName();\r
-            if (host != null) {\r
-                try {\r
-                    server = host.getBytes("UnicodeLittleUnmarked");\r
-                } catch (IOException ex) { }\r
-            }\r
-        } catch (UnknownHostException ex) { }\r
-        int serverLength = server.length;\r
-        byte[] targetInfo = new byte[(domainLength > 0 ? domainLength + 4 : 0) +\r
-                (serverLength > 0 ? serverLength + 4 : 0) + 4];\r
-        int offset = 0;\r
-        if (domainLength > 0) {\r
-            writeUShort(targetInfo, offset, 2);\r
-            offset += 2;\r
-            writeUShort(targetInfo, offset, domainLength);\r
-            offset += 2;\r
-            System.arraycopy(domain, 0, targetInfo, offset, domainLength);\r
-            offset += domainLength;\r
-        }\r
-        if (serverLength > 0) {\r
-            writeUShort(targetInfo, offset, 1);\r
-            offset += 2;\r
-            writeUShort(targetInfo, offset, serverLength);\r
-            offset += 2;\r
-            System.arraycopy(server, 0, targetInfo, offset, serverLength);\r
-        }\r
-        DEFAULT_TARGET_INFORMATION = targetInfo;\r
-    }\r
-\r
-    /**\r
-     * Creates a Type-2 message using default values from the current\r
-     * environment.\r
-     */\r
-    public Type2Message() {\r
-        this(getDefaultFlags(), null, null);\r
-    }\r
-\r
-    /**\r
-     * Creates a Type-2 message in response to the given Type-1 message\r
-     * using default values from the current environment.\r
-     *\r
-     * @param type1 The Type-1 message which this represents a response to.\r
-     */\r
-    public Type2Message(Type1Message type1) {\r
-        this(type1, null, null);\r
-    }\r
-\r
-    /**\r
-     * Creates a Type-2 message in response to the given Type-1 message.\r
-     *\r
-     * @param type1 The Type-1 message which this represents a response to.\r
-     * @param challenge The challenge from the domain controller/server.\r
-     * @param target The authentication target.\r
-     */\r
-    public Type2Message(Type1Message type1, byte[] challenge, String target) {\r
-        this(getDefaultFlags(type1), challenge, (type1 != null &&\r
-                target == null && type1.getFlag(NTLMSSP_REQUEST_TARGET)) ?\r
-                        getDefaultDomain() : target);\r
-    }\r
-\r
-    /**\r
-     * Creates a Type-2 message with the specified parameters.\r
-     *\r
-     * @param flags The flags to apply to this message.\r
-     * @param challenge The challenge from the domain controller/server.\r
-     * @param target The authentication target.\r
-     */\r
-    public Type2Message(int flags, byte[] challenge, String target) {\r
-        setFlags(flags);\r
-        setChallenge(challenge);\r
-        setTarget(target);\r
-        if (target != null) setTargetInformation(getDefaultTargetInformation());\r
-    }\r
-\r
-    /**\r
-     * Creates a Type-2 message using the given raw Type-2 material.\r
-     *\r
-     * @param material The raw Type-2 material used to construct this message.\r
-     * @throws IOException If an error occurs while parsing the material.\r
-     */\r
-    public Type2Message(byte[] material) throws IOException {\r
-        parse(material);\r
-    }\r
-\r
-    /**\r
-     * Returns the challenge for this message.\r
-     *\r
-     * @return A <code>byte[]</code> containing the challenge.\r
-     */\r
-    public byte[] getChallenge() {\r
-        return challenge;\r
-    }\r
-\r
-    /**\r
-     * Sets the challenge for this message.\r
-     *\r
-     * @param challenge The challenge from the domain controller/server.\r
-     */\r
-    public void setChallenge(byte[] challenge) {\r
-        this.challenge = challenge;\r
-    }\r
-\r
-    /**\r
-     * Returns the authentication target.\r
-     *\r
-     * @return A <code>String</code> containing the authentication target.\r
-     */\r
-    public String getTarget() {\r
-        return target;\r
-    }\r
-\r
-    /**\r
-     * Sets the authentication target.\r
-     *\r
-     * @param target The authentication target.\r
-     */\r
-    public void setTarget(String target) {\r
-        this.target = target;\r
-    }\r
-\r
-    /**\r
-     * Returns the target information block.\r
-     *\r
-     * @return A <code>byte[]</code> containing the target information block.\r
-     * The target information block is used by the client to create an\r
-     * NTLMv2 response.\r
-     */ \r
-    public byte[] getTargetInformation() {\r
-        return targetInformation;\r
-    }\r
-\r
-    /**\r
-     * Sets the target information block.\r
-     * The target information block is used by the client to create\r
-     * an NTLMv2 response.\r
-     * \r
-     * @param targetInformation The target information block.\r
-     */\r
-    public void setTargetInformation(byte[] targetInformation) {\r
-        this.targetInformation = targetInformation;\r
-    }\r
-\r
-    /**\r
-     * Returns the local security context.\r
-     *\r
-     * @return A <code>byte[]</code> containing the local security\r
-     * context.  This is used by the client to negotiate local\r
-     * authentication.\r
-     */\r
-    public byte[] getContext() {\r
-        return context;\r
-    }\r
-\r
-    /**\r
-     * Sets the local security context.  This is used by the client\r
-     * to negotiate local authentication.\r
-     *\r
-     * @param context The local security context.\r
-     */\r
-    public void setContext(byte[] context) {\r
-        this.context = context;\r
-    }\r
-\r
-    public byte[] toByteArray() {\r
-        try {\r
-            String targetName = getTarget();\r
-            byte[] challenge = getChallenge();\r
-            byte[] context = getContext();\r
-            byte[] targetInformation = getTargetInformation();\r
-            int flags = getFlags();\r
-            byte[] target = new byte[0];\r
-            if ((flags & (NTLMSSP_TARGET_TYPE_DOMAIN |\r
-                    NTLMSSP_TARGET_TYPE_SERVER |\r
-                            NTLMSSP_TARGET_TYPE_SHARE)) != 0) {\r
-                if (targetName != null && targetName.length() != 0) {\r
-                    target = (flags & NTLMSSP_NEGOTIATE_UNICODE) != 0 ?\r
-                            targetName.getBytes("UnicodeLittleUnmarked") :\r
-                            targetName.toUpperCase().getBytes(getOEMEncoding());\r
-                } else {\r
-                    flags &= (0xffffffff ^ (NTLMSSP_TARGET_TYPE_DOMAIN |\r
-                            NTLMSSP_TARGET_TYPE_SERVER |\r
-                                    NTLMSSP_TARGET_TYPE_SHARE));\r
-                }\r
-            }\r
-            if (targetInformation != null) {\r
-                flags ^= NTLMSSP_NEGOTIATE_TARGET_INFO;\r
-                // empty context is needed for padding when t.i. is supplied.\r
-                if (context == null) context = new byte[8];\r
-            }\r
-            int data = 32;\r
-            if (context != null) data += 8;\r
-            if (targetInformation != null) data += 8;\r
-            byte[] type2 = new byte[data + target.length +\r
-                    (targetInformation != null ? targetInformation.length : 0)];\r
-            System.arraycopy(NTLMSSP_SIGNATURE, 0, type2, 0, 8);\r
-            writeULong(type2, 8, 2);\r
-            writeSecurityBuffer(type2, 12, data, target);\r
-            writeULong(type2, 20, flags);\r
-            System.arraycopy(challenge != null ? challenge : new byte[8], 0,\r
-                    type2, 24, 8);\r
-            if (context != null) System.arraycopy(context, 0, type2, 32, 8);\r
-            if (targetInformation != null) {\r
-                writeSecurityBuffer(type2, 40, data + target.length,\r
-                        targetInformation);\r
-            }\r
-            return type2;\r
-        } catch (IOException ex) {\r
-            throw new IllegalStateException(ex.getMessage());\r
-        }\r
-    }\r
-\r
-    public String toString() {\r
-        String target = getTarget();\r
-        byte[] challenge = getChallenge();\r
-        byte[] context = getContext();\r
-        byte[] targetInformation = getTargetInformation();\r
-        int flags = getFlags();\r
-        StringBuffer buffer = new StringBuffer();\r
-        if (target != null) {\r
-            buffer.append("target: ").append(target);\r
-        }\r
-        if (challenge != null) {\r
-            if (buffer.length() > 0) buffer.append("; ");\r
-            buffer.append("challenge: ");\r
-            buffer.append("0x");\r
-            for (int i = 0; i < challenge.length; i++) {\r
-                buffer.append(Integer.toHexString((challenge[i] >> 4) & 0x0f));\r
-                buffer.append(Integer.toHexString(challenge[i] & 0x0f));\r
-            }\r
-        }\r
-        if (context != null) {\r
-            if (buffer.length() > 0) buffer.append("; ");\r
-            buffer.append("context: ");\r
-            buffer.append("0x");\r
-            for (int i = 0; i < context.length; i++) {\r
-                buffer.append(Integer.toHexString((context[i] >> 4) & 0x0f));\r
-                buffer.append(Integer.toHexString(context[i] & 0x0f));\r
-            }\r
-        }\r
-        if (targetInformation != null) {\r
-            if (buffer.length() > 0) buffer.append("; ");\r
-            buffer.append("targetInformation: ");\r
-            buffer.append("0x");\r
-            for (int i = 0; i < targetInformation.length; i++) {\r
-                buffer.append(Integer.toHexString((targetInformation[i] >> 4) &\r
-                        0x0f));\r
-                buffer.append(Integer.toHexString(targetInformation[i] & 0x0f));\r
-            }\r
-        }\r
-        if (flags != 0) {\r
-            if (buffer.length() > 0) buffer.append("; ");\r
-            buffer.append("flags: ");\r
-            buffer.append("0x");\r
-            buffer.append(Integer.toHexString((flags >> 28) & 0x0f));\r
-            buffer.append(Integer.toHexString((flags >> 24) & 0x0f));\r
-            buffer.append(Integer.toHexString((flags >> 20) & 0x0f));\r
-            buffer.append(Integer.toHexString((flags >> 16) & 0x0f));\r
-            buffer.append(Integer.toHexString((flags >> 12) & 0x0f));\r
-            buffer.append(Integer.toHexString((flags >> 8) & 0x0f));\r
-            buffer.append(Integer.toHexString((flags >> 4) & 0x0f));\r
-            buffer.append(Integer.toHexString(flags & 0x0f));\r
-        }\r
-        return buffer.toString();\r
-    }\r
-\r
-    /**\r
-     * Returns the default flags for a generic Type-2 message in the\r
-     * current environment.\r
-     *\r
-     * @return An <code>int</code> containing the default flags.\r
-     */\r
-    public static int getDefaultFlags() {\r
-        return DEFAULT_FLAGS;\r
-    }\r
-\r
-    /**\r
-     * Returns the default flags for a Type-2 message created in response\r
-     * to the given Type-1 message in the current environment.\r
-     *\r
-     * @return An <code>int</code> containing the default flags.\r
-     */\r
-    public static int getDefaultFlags(Type1Message type1) {\r
-        if (type1 == null) return DEFAULT_FLAGS;\r
-        int flags = NTLMSSP_NEGOTIATE_NTLM;\r
-        int type1Flags = type1.getFlags();\r
-        flags |= ((type1Flags & NTLMSSP_NEGOTIATE_UNICODE) != 0) ?\r
-                NTLMSSP_NEGOTIATE_UNICODE : NTLMSSP_NEGOTIATE_OEM;\r
-        if ((type1Flags & NTLMSSP_REQUEST_TARGET) != 0) {\r
-            String domain = getDefaultDomain();\r
-            if (domain != null) {\r
-                flags |= NTLMSSP_REQUEST_TARGET | NTLMSSP_TARGET_TYPE_DOMAIN;\r
-            }\r
-        }\r
-        return flags;\r
-    }\r
-\r
-    /**\r
-     * Returns the default domain from the current environment.\r
-     *\r
-     * @return A <code>String</code> containing the domain.\r
-     */\r
-    public static String getDefaultDomain() {\r
-        return DEFAULT_DOMAIN;\r
-    }\r
-\r
-    public static byte[] getDefaultTargetInformation() {\r
-        return DEFAULT_TARGET_INFORMATION;\r
-    }\r
-\r
-    private void parse(byte[] material) throws IOException {\r
-        for (int i = 0; i < 8; i++) {\r
-            if (material[i] != NTLMSSP_SIGNATURE[i]) {\r
-                throw new IOException("Not an NTLMSSP message.");\r
-            }\r
-        }\r
-        if (readULong(material, 8) != 2) {\r
-            throw new IOException("Not a Type 2 message.");\r
-        }\r
-        int flags = readULong(material, 20);\r
-        setFlags(flags);\r
-        String target = null;\r
-        byte[] bytes = readSecurityBuffer(material, 12);\r
-        if (bytes.length != 0) {\r
-            target = new String(bytes,\r
-                    ((flags & NTLMSSP_NEGOTIATE_UNICODE) != 0) ?\r
-                            "UnicodeLittleUnmarked" : getOEMEncoding());\r
-        }\r
-        setTarget(target);\r
-        for (int i = 24; i < 32; i++) {\r
-            if (material[i] != 0) {\r
-                byte[] challenge = new byte[8];\r
-                System.arraycopy(material, 24, challenge, 0, 8);\r
-                setChallenge(challenge);\r
-                break;\r
-            }\r
-        }\r
-        int offset = readULong(material, 16); // offset of targetname start\r
-        if (offset == 32 || material.length == 32) return;\r
-        for (int i = 32; i < 40; i++) {\r
-            if (material[i] != 0) {\r
-                byte[] context = new byte[8];\r
-                System.arraycopy(material, 32, context, 0, 8);\r
-                setContext(context);\r
-                break;\r
-            }\r
-        }\r
-        if (offset == 40 || material.length == 40) return;\r
-        bytes = readSecurityBuffer(material, 40);\r
-        if (bytes.length != 0) setTargetInformation(bytes);\r
-    }\r
-\r
-}\r
diff --git a/update/Type3Message.java b/update/Type3Message.java
deleted file mode 100644 (file)
index 123b703..0000000
+++ /dev/null
@@ -1,580 +0,0 @@
-/* jcifs smb client library in Java\r
- * Copyright (C) 2002  "Michael B. Allen" <jcifs at samba dot org>\r
- *                   "Eric Glass" <jcifs at samba dot org>\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
- */\r
-\r
-package jcifs.ntlmssp;\r
-\r
-import java.io.IOException;\r
-\r
-import java.net.UnknownHostException;\r
-\r
-import java.security.SecureRandom;\r
-\r
-import jcifs.Config;\r
-\r
-import jcifs.netbios.NbtAddress;\r
-\r
-import jcifs.smb.NtlmPasswordAuthentication;\r
-\r
-/**\r
- * Represents an NTLMSSP Type-3 message.\r
- */\r
-public class Type3Message extends NtlmMessage {\r
-\r
-    private static final int DEFAULT_FLAGS;\r
-\r
-    private static final String DEFAULT_DOMAIN;\r
-\r
-    private static final String DEFAULT_USER;\r
-\r
-    private static final String DEFAULT_PASSWORD;\r
-\r
-    private static final String DEFAULT_WORKSTATION;\r
-\r
-    private static final int LM_COMPATIBILITY;\r
-\r
-    private static final SecureRandom RANDOM = new SecureRandom();\r
-\r
-    private byte[] lmResponse;\r
-\r
-    private byte[] ntResponse;\r
-\r
-    private String domain;\r
-\r
-    private String user;\r
-\r
-    private String workstation;\r
-\r
-    private byte[] sessionKey;\r
-\r
-    static {\r
-        DEFAULT_FLAGS = NTLMSSP_NEGOTIATE_NTLM |\r
-                (Config.getBoolean("jcifs.smb.client.useUnicode", true) ?\r
-                        NTLMSSP_NEGOTIATE_UNICODE : NTLMSSP_NEGOTIATE_OEM);\r
-        DEFAULT_DOMAIN = Config.getProperty("jcifs.smb.client.domain", null);\r
-        DEFAULT_USER = Config.getProperty("jcifs.smb.client.username", null);\r
-        DEFAULT_PASSWORD = Config.getProperty("jcifs.smb.client.password",\r
-                null);\r
-        String defaultWorkstation = null;\r
-        try {\r
-            defaultWorkstation = NbtAddress.getLocalHost().getHostName();\r
-        } catch (UnknownHostException ex) { }\r
-        DEFAULT_WORKSTATION = defaultWorkstation;\r
-        LM_COMPATIBILITY = Config.getInt("jcifs.smb.lmCompatibility", 0);\r
-    }\r
-\r
-    /**\r
-     * Creates a Type-3 message using default values from the current\r
-     * environment.\r
-     */\r
-    public Type3Message() {\r
-        setFlags(getDefaultFlags());\r
-        setDomain(getDefaultDomain());\r
-        setUser(getDefaultUser());\r
-        setWorkstation(getDefaultWorkstation());\r
-    }\r
-\r
-    /**\r
-     * Creates a Type-3 message in response to the given Type-2 message\r
-     * using default values from the current environment.\r
-     *\r
-     * @param type2 The Type-2 message which this represents a response to.\r
-     */\r
-    public Type3Message(Type2Message type2) {\r
-        setFlags(getDefaultFlags(type2));\r
-        setWorkstation(getDefaultWorkstation());\r
-        String domain = getDefaultDomain();\r
-        setDomain(domain);\r
-        String user = getDefaultUser();\r
-        setUser(user);\r
-        String password = getDefaultPassword();\r
-        switch (LM_COMPATIBILITY) {\r
-        case 0:\r
-        case 1:\r
-            setLMResponse(getLMResponse(type2, password));\r
-            setNTResponse(getNTResponse(type2, password));\r
-            break;\r
-        case 2:\r
-            byte[] nt = getNTResponse(type2, password);\r
-            setLMResponse(nt);\r
-            setNTResponse(nt);\r
-            break;\r
-        case 3:\r
-        case 4:\r
-        case 5:\r
-            byte[] clientChallenge = new byte[8];\r
-            RANDOM.nextBytes(clientChallenge);\r
-            setLMResponse(getLMv2Response(type2, domain, user, password,\r
-                    clientChallenge));\r
-            /*\r
-            setNTResponse(getNTLMv2Response(type2, domain, user, password,\r
-                    clientChallenge));\r
-            */\r
-            break;\r
-        default:\r
-            setLMResponse(getLMResponse(type2, password));\r
-            setNTResponse(getNTResponse(type2, password));\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Creates a Type-3 message in response to the given Type-2 message.\r
-     *\r
-     * @param type2 The Type-2 message which this represents a response to.\r
-     * @param password The password to use when constructing the response.\r
-     * @param domain The domain in which the user has an account.\r
-     * @param user The username for the authenticating user.\r
-     * @param workstation The workstation from which authentication is\r
-     * taking place.\r
-     */\r
-    public Type3Message(Type2Message type2, String password, String domain,\r
-            String user, String workstation) {\r
-        setFlags(getDefaultFlags(type2));\r
-        setDomain(domain);\r
-        setUser(user);\r
-        setWorkstation(workstation);\r
-        switch (LM_COMPATIBILITY) {\r
-        case 0:\r
-        case 1:\r
-            setLMResponse(getLMResponse(type2, password));\r
-            setNTResponse(getNTResponse(type2, password));\r
-            break;\r
-        case 2:\r
-            byte[] nt = getNTResponse(type2, password);\r
-            setLMResponse(nt);\r
-            setNTResponse(nt);\r
-            break;\r
-        case 3:\r
-        case 4:\r
-        case 5:\r
-            byte[] clientChallenge = new byte[8];\r
-            RANDOM.nextBytes(clientChallenge);\r
-            setLMResponse(getLMv2Response(type2, domain, user, password,\r
-                    clientChallenge));\r
-            /*\r
-            setNTResponse(getNTLMv2Response(type2, domain, user, password,\r
-                    clientChallenge));\r
-            */\r
-            break;\r
-        default:\r
-            setLMResponse(getLMResponse(type2, password));\r
-            setNTResponse(getNTResponse(type2, password));\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Creates a Type-3 message with the specified parameters.\r
-     *\r
-     * @param flags The flags to apply to this message.\r
-     * @param lmResponse The LanManager/LMv2 response.\r
-     * @param domain The NT/NTLMv2 response.\r
-     * @param domain The domain in which the user has an account.\r
-     * @param user The username for the authenticating user.\r
-     * @param workstation The workstation from which authentication is\r
-     * taking place.\r
-     */\r
-    public Type3Message(int flags, byte[] lmResponse, byte[] ntResponse,\r
-            String domain, String user, String workstation) {\r
-        setFlags(flags);\r
-        setLMResponse(lmResponse);\r
-        setNTResponse(ntResponse);\r
-        setDomain(domain);\r
-        setUser(user);\r
-        setWorkstation(workstation);\r
-    }\r
-\r
-    /**\r
-     * Creates a Type-3 message using the given raw Type-3 material.\r
-     *\r
-     * @param material The raw Type-3 material used to construct this message.\r
-     * @throws IOException If an error occurs while parsing the material.\r
-     */\r
-    public Type3Message(byte[] material) throws IOException {\r
-        parse(material);\r
-    }\r
-\r
-    /**\r
-     * Returns the LanManager/LMv2 response.\r
-     *\r
-     * @return A <code>byte[]</code> containing the LanManager response.\r
-     */\r
-    public byte[] getLMResponse() {\r
-        return lmResponse;\r
-    }\r
-\r
-    /**\r
-     * Sets the LanManager/LMv2 response for this message.\r
-     *\r
-     * @param lmResponse The LanManager response.\r
-     */\r
-    public void setLMResponse(byte[] lmResponse) {\r
-        this.lmResponse = lmResponse;\r
-    }\r
-\r
-    /**\r
-     * Returns the NT/NTLMv2 response.\r
-     *\r
-     * @return A <code>byte[]</code> containing the NT/NTLMv2 response.\r
-     */\r
-    public byte[] getNTResponse() {\r
-        return ntResponse;\r
-    }\r
-\r
-    /**\r
-     * Sets the NT/NTLMv2 response for this message.\r
-     *\r
-     * @param lmResponse The NT/NTLMv2 response.\r
-     */\r
-    public void setNTResponse(byte[] ntResponse) {\r
-        this.ntResponse = ntResponse;\r
-    }\r
-\r
-    /**\r
-     * Returns the domain in which the user has an account.\r
-     *\r
-     * @return A <code>String</code> containing the domain for the user.\r
-     */\r
-    public String getDomain() {\r
-        return domain;\r
-    }\r
-\r
-    /**\r
-     * Sets the domain for this message.\r
-     *\r
-     * @param domain The domain.\r
-     */\r
-    public void setDomain(String domain) {\r
-        this.domain = domain;\r
-    }\r
-\r
-    /**\r
-     * Returns the username for the authenticating user.\r
-     *\r
-     * @return A <code>String</code> containing the user for this message.\r
-     */\r
-    public String getUser() {\r
-        return user;\r
-    }\r
-\r
-    /**\r
-     * Sets the user for this message.\r
-     *\r
-     * @param user The user.\r
-     */\r
-    public void setUser(String user) {\r
-        this.user = user;\r
-    }\r
-\r
-    /**\r
-     * Returns the workstation from which authentication is being performed.\r
-     *\r
-     * @return A <code>String</code> containing the workstation.\r
-     */\r
-    public String getWorkstation() {\r
-        return workstation;\r
-    }\r
-\r
-    /**\r
-     * Sets the workstation for this message.\r
-     *\r
-     * @param workstation The workstation.\r
-     */\r
-    public void setWorkstation(String workstation) {\r
-        this.workstation = workstation;\r
-    }\r
-\r
-    /**\r
-     * Returns the session key.\r
-     *\r
-     * @return A <code>byte[]</code> containing the session key.\r
-     */\r
-    public byte[] getSessionKey() {\r
-        return sessionKey;\r
-    }\r
-\r
-    /**\r
-     * Sets the session key.\r
-     *\r
-     * @param sessionKey The session key.\r
-     */\r
-    public void setSessionKey(byte[] sessionKey) {\r
-        this.sessionKey = sessionKey;\r
-    }\r
-\r
-    public byte[] toByteArray() {\r
-        try {\r
-            int flags = getFlags();\r
-            boolean unicode = (flags & NTLMSSP_NEGOTIATE_UNICODE) != 0;\r
-            String oem = unicode ? null : getOEMEncoding();\r
-            String domainName = getDomain();\r
-            byte[] domain = null;\r
-            if (domainName != null && domainName.length() != 0) {\r
-                domain = unicode ?\r
-                        domainName.getBytes("UnicodeLittleUnmarked") :\r
-                                domainName.toUpperCase().getBytes(oem);\r
-            }\r
-            int domainLength = (domain != null) ? domain.length : 0;\r
-            String userName = getUser();\r
-            byte[] user = null;\r
-            if (userName != null && userName.length() != 0) {\r
-                user = unicode ? userName.getBytes("UnicodeLittleUnmarked") :\r
-                        userName.toUpperCase().getBytes(oem);\r
-            }\r
-            int userLength = (user != null) ? user.length : 0;\r
-            String workstationName = getWorkstation();\r
-            byte[] workstation = null;\r
-            if (workstationName != null && workstationName.length() != 0) {\r
-                workstation = unicode ?\r
-                        workstationName.getBytes("UnicodeLittleUnmarked") :\r
-                                workstationName.toUpperCase().getBytes(oem);\r
-            }\r
-            int workstationLength = (workstation != null) ?\r
-                    workstation.length : 0;\r
-            byte[] lmResponse = getLMResponse();\r
-            int lmLength = (lmResponse != null) ? lmResponse.length : 0;\r
-            byte[] ntResponse = getNTResponse();\r
-            int ntLength = (ntResponse != null) ? ntResponse.length : 0;\r
-            byte[] sessionKey = getSessionKey();\r
-            int keyLength = (sessionKey != null) ? sessionKey.length : 0;\r
-            byte[] type3 = new byte[64 + domainLength + userLength +\r
-                    workstationLength + lmLength + ntLength + keyLength];\r
-            System.arraycopy(NTLMSSP_SIGNATURE, 0, type3, 0, 8);\r
-            writeULong(type3, 8, 3);\r
-            int offset = 64;\r
-            writeSecurityBuffer(type3, 12, offset, lmResponse);\r
-            offset += lmLength;\r
-            writeSecurityBuffer(type3, 20, offset, ntResponse);\r
-            offset += ntLength;\r
-            writeSecurityBuffer(type3, 28, offset, domain);\r
-            offset += domainLength;\r
-            writeSecurityBuffer(type3, 36, offset, user);\r
-            offset += userLength;\r
-            writeSecurityBuffer(type3, 44, offset, workstation);\r
-            offset += workstationLength;\r
-            writeSecurityBuffer(type3, 52, offset, sessionKey);\r
-            writeULong(type3, 60, flags);\r
-            return type3;\r
-        } catch (IOException ex) {\r
-            throw new IllegalStateException(ex.getMessage());\r
-        }\r
-    }\r
-\r
-    public String toString() {\r
-        String user = getUser();\r
-        String domain = getDomain();\r
-        String workstation = getWorkstation();\r
-        byte[] lmResponse = getLMResponse();\r
-        byte[] ntResponse = getNTResponse();\r
-        byte[] sessionKey = getSessionKey();\r
-        int flags = getFlags();\r
-        StringBuffer buffer = new StringBuffer();\r
-        if (domain != null) {\r
-            buffer.append("domain: ").append(domain);\r
-        }\r
-        if (user != null) {\r
-            if (buffer.length() > 0) buffer.append("; ");\r
-            buffer.append("user: ").append(user);\r
-        }\r
-        if (workstation != null) {\r
-            if (buffer.length() > 0) buffer.append("; ");\r
-            buffer.append("workstation: ").append(workstation);\r
-        }\r
-        if (lmResponse != null) {\r
-            if (buffer.length() > 0) buffer.append("; ");\r
-            buffer.append("lmResponse: ");\r
-            buffer.append("0x");\r
-            for (int i = 0; i < lmResponse.length; i++) {\r
-                buffer.append(Integer.toHexString((lmResponse[i] >> 4) & 0x0f));\r
-                buffer.append(Integer.toHexString(lmResponse[i] & 0x0f));\r
-            }\r
-        }\r
-        if (ntResponse != null) {\r
-            if (buffer.length() > 0) buffer.append("; ");\r
-            buffer.append("ntResponse: ");\r
-            buffer.append("0x");\r
-            for (int i = 0; i < ntResponse.length; i++) {\r
-                buffer.append(Integer.toHexString((ntResponse[i] >> 4) & 0x0f));\r
-                buffer.append(Integer.toHexString(ntResponse[i] & 0x0f));\r
-            }\r
-        }\r
-        if (sessionKey != null) {\r
-            if (buffer.length() > 0) buffer.append("; ");\r
-            buffer.append("sessionKey: ");\r
-            buffer.append("0x");\r
-            for (int i = 0; i < sessionKey.length; i++) {\r
-                buffer.append(Integer.toHexString((sessionKey[i] >> 4) & 0x0f));\r
-                buffer.append(Integer.toHexString(sessionKey[i] & 0x0f));\r
-            }\r
-        }\r
-        if (flags != 0) {\r
-            if (buffer.length() > 0) buffer.append("; ");\r
-            buffer.append("flags: ");\r
-            buffer.append("0x");\r
-            buffer.append(Integer.toHexString((flags >> 28) & 0x0f));\r
-            buffer.append(Integer.toHexString((flags >> 24) & 0x0f));\r
-            buffer.append(Integer.toHexString((flags >> 20) & 0x0f));\r
-            buffer.append(Integer.toHexString((flags >> 16) & 0x0f));\r
-            buffer.append(Integer.toHexString((flags >> 12) & 0x0f));\r
-            buffer.append(Integer.toHexString((flags >> 8) & 0x0f));\r
-            buffer.append(Integer.toHexString((flags >> 4) & 0x0f));\r
-            buffer.append(Integer.toHexString(flags & 0x0f));\r
-        }\r
-        return buffer.toString();\r
-    }\r
-\r
-    /**\r
-     * Returns the default flags for a generic Type-3 message in the\r
-     * current environment.\r
-     *\r
-     * @return An <code>int</code> containing the default flags.\r
-     */\r
-    public static int getDefaultFlags() {\r
-        return DEFAULT_FLAGS;\r
-    }\r
-\r
-    /**\r
-     * Returns the default flags for a Type-3 message created in response\r
-     * to the given Type-2 message in the current environment.\r
-     *\r
-     * @return An <code>int</code> containing the default flags.\r
-     */\r
-    public static int getDefaultFlags(Type2Message type2) {\r
-        if (type2 == null) return DEFAULT_FLAGS;\r
-        int flags = NTLMSSP_NEGOTIATE_NTLM;\r
-        flags |= ((type2.getFlags() & NTLMSSP_NEGOTIATE_UNICODE) != 0) ?\r
-                NTLMSSP_NEGOTIATE_UNICODE : NTLMSSP_NEGOTIATE_OEM;\r
-        return flags;\r
-    }\r
-\r
-    /**\r
-     * Constructs the LanManager response to the given Type-2 message using\r
-     * the supplied password.\r
-     *\r
-     * @param type2 The Type-2 message.\r
-     * @param password The password.\r
-     * @return A <code>byte[]</code> containing the LanManager response.\r
-     */\r
-    public static byte[] getLMResponse(Type2Message type2, String password) {\r
-        if (type2 == null || password == null) return null;\r
-        return NtlmPasswordAuthentication.getPreNTLMResponse(password,\r
-                type2.getChallenge());\r
-    }\r
-\r
-    public static byte[] getLMv2Response(Type2Message type2,\r
-            String domain, String user, String password,\r
-                    byte[] clientChallenge) {\r
-        if (type2 == null || domain == null || user == null ||\r
-                password == null || clientChallenge == null) {\r
-            return null;\r
-        }\r
-        return NtlmPasswordAuthentication.getLMv2Response(domain, user,\r
-                password, type2.getChallenge(), clientChallenge);\r
-    }\r
-\r
-    /**\r
-     * Constructs the NT response to the given Type-2 message using\r
-     * the supplied password.\r
-     *\r
-     * @param type2 The Type-2 message.\r
-     * @param password The password.\r
-     * @return A <code>byte[]</code> containing the NT response.\r
-     */\r
-    public static byte[] getNTResponse(Type2Message type2, String password) {\r
-        if (type2 == null || password == null) return null;\r
-        return NtlmPasswordAuthentication.getNTLMResponse(password,\r
-                type2.getChallenge());\r
-    }\r
-\r
-    /**\r
-     * Returns the default domain from the current environment.\r
-     *\r
-     * @return The default domain.\r
-     */\r
-    public static String getDefaultDomain() {\r
-        return DEFAULT_DOMAIN;\r
-    }\r
-\r
-    /**\r
-     * Returns the default user from the current environment.\r
-     *\r
-     * @return The default user.\r
-     */\r
-    public static String getDefaultUser() {\r
-        return DEFAULT_USER;\r
-    }\r
-\r
-    /**\r
-     * Returns the default password from the current environment.\r
-     *\r
-     * @return The default password.\r
-     */\r
-    public static String getDefaultPassword() {\r
-        return DEFAULT_PASSWORD;\r
-    }\r
-\r
-    /**\r
-     * Returns the default workstation from the current environment.\r
-     *\r
-     * @return The default workstation.\r
-     */\r
-    public static String getDefaultWorkstation() {\r
-        return DEFAULT_WORKSTATION;\r
-    }\r
-\r
-    private void parse(byte[] material) throws IOException {\r
-        for (int i = 0; i < 8; i++) {\r
-            if (material[i] != NTLMSSP_SIGNATURE[i]) {\r
-                throw new IOException("Not an NTLMSSP message.");\r
-            }\r
-        }\r
-        if (readULong(material, 8) != 3) {\r
-            throw new IOException("Not a Type 3 message.");\r
-        }\r
-        byte[] lmResponse = readSecurityBuffer(material, 12);\r
-        int lmResponseOffset = readULong(material, 16);\r
-        byte[] ntResponse = readSecurityBuffer(material, 20);\r
-        int ntResponseOffset = readULong(material, 24);\r
-        byte[] domain = readSecurityBuffer(material, 28);\r
-        int domainOffset = readULong(material, 32);\r
-        byte[] user = readSecurityBuffer(material, 36);\r
-        int userOffset = readULong(material, 40);\r
-        byte[] workstation = readSecurityBuffer(material, 44);\r
-        int workstationOffset = readULong(material, 48);\r
-        int flags;\r
-        String charset;\r
-        if (lmResponseOffset == 52 || ntResponseOffset == 52 ||\r
-                domainOffset == 52 || userOffset == 52 ||\r
-                        workstationOffset == 52) {\r
-            flags = NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_OEM;\r
-            charset = getOEMEncoding();\r
-        } else {\r
-            setSessionKey(readSecurityBuffer(material, 52));\r
-            flags = readULong(material, 60);\r
-            charset = ((flags & NTLMSSP_NEGOTIATE_UNICODE) != 0) ?\r
-                "UnicodeLittleUnmarked" : getOEMEncoding();\r
-        }\r
-        setFlags(flags);\r
-        setLMResponse(lmResponse);\r
-        // NTLMv2 issues w/cross-domain authentication; leave NT empty if >= 3\r
-        if (LM_COMPATIBILITY < 3) setNTResponse(ntResponse);\r
-        setDomain(new String(domain, charset));\r
-        setUser(new String(user, charset));\r
-        setWorkstation(new String(workstation, charset));\r
-    }\r
-\r
-}\r