From: Felix Schumacher Date: Sat, 15 Aug 2009 09:35:22 +0000 (+0200) Subject: jcifs-1.3.12 from tgz X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=80f1ad0a2378183ff0e8b569909e27123ddbeb03;p=jcifs_without_docs.git jcifs-1.3.12 from tgz Fri Aug 14 13:45:57 EDT 2009 jcifs-1.3.12 If NtlmPasswordAuthentication.ANONYMOUS was used, CAP_EXTENDED_SECURITY could be incorrectly turned off resulting in a NullPointerException in SmbComSessionSetupAndX.java. If a DC does not return any domain referrals, a NullPointerException could occur. Both of these NPEs have been fixed. JCIFS could become confused when connecting to a server that also happened to be a DFS root server. JCIFS will now create separate transports for these two cases. --- diff --git a/README.txt b/README.txt index 9faf634..04d014e 100644 --- a/README.txt +++ b/README.txt @@ -1,11 +1,15 @@ -Tue Aug 4 14:31:47 EDT 2009 -jcifs-1.3.12c +Fri Aug 14 13:45:57 EDT 2009 +jcifs-1.3.12 If NtlmPasswordAuthentication.ANONYMOUS was used, CAP_EXTENDED_SECURITY could be incorrectly turned off resulting in a NullPointerException in SmbComSessionSetupAndX.java. If a DC does not return any domain referrals, a NullPointerException could occur. Both of these NPEs have been fixed. +JCIFS could become confused when connecting to a server that also happened +to be a DFS root server. JCIFS will now create separate transports for +these two cases. + Tue Jul 21 11:19:39 EDT 2009 jcifs-1.3.11 diff --git a/build.xml b/build.xml index 361af62..0fae674 100644 --- a/build.xml +++ b/build.xml @@ -1,7 +1,7 @@ - - + + diff --git a/examples/runtests.sh b/examples/runtests.sh index 6cd4e6e..d648054 100644 --- a/examples/runtests.sh +++ b/examples/runtests.sh @@ -6,15 +6,15 @@ PROPERTIES=../../user2.prp RUN="${JAVA_HOME}/bin/java -cp ${CLASSPATH} -Djcifs.properties=${PROPERTIES}" #SERVER=192.168.2.110 -SERVER=dc1.w.net -SHARE=tmp -DIR=test +#SERVER=dc1.w.net +#SHARE=tmp +#DIR=test # Domain-based DFS #SERVER=192.168.2.110 -#SERVER=w.net -#SHARE=root2 -#DIR=test +SERVER=w.net +SHARE=root2 +DIR=test # smb://fs1.w.net/DFSStandaloneRoot/DFSStandaloneLink/test/ # smb://dc1.w.net/root2/link2/test/ diff --git a/src/jcifs/smb/NtStatus.java b/src/jcifs/smb/NtStatus.java index cf9594e..7eeabf1 100644 --- a/src/jcifs/smb/NtStatus.java +++ b/src/jcifs/smb/NtStatus.java @@ -80,6 +80,7 @@ public interface NtStatus { public static final int NT_STATUS_LOGON_TYPE_NOT_GRANTED = 0xC000015b; public static final int NT_STATUS_NO_TRUST_SAM_ACCOUNT = 0xC000018b; public static final int NT_STATUS_TRUSTED_DOMAIN_FAILURE = 0xC000018c; + public static final int NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT = 0xC0000199; public static final int NT_STATUS_PASSWORD_MUST_CHANGE = 0xC0000224; public static final int NT_STATUS_NOT_FOUND = 0xC0000225; public static final int NT_STATUS_ACCOUNT_LOCKED_OUT = 0xC0000234; @@ -143,6 +144,7 @@ public interface NtStatus { NT_STATUS_LOGON_TYPE_NOT_GRANTED, NT_STATUS_NO_TRUST_SAM_ACCOUNT, NT_STATUS_TRUSTED_DOMAIN_FAILURE, + NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, NT_STATUS_PASSWORD_MUST_CHANGE, NT_STATUS_NOT_FOUND, NT_STATUS_ACCOUNT_LOCKED_OUT, @@ -207,6 +209,7 @@ public interface NtStatus { "Logon failure: the user has not been granted the requested logon type at this computer.", "The SAM database on the Windows NT Server does not have a computer account for this workstation trust relationship.", "The trust relationship between the primary domain and the trusted domain failed.", + "The account used is a Computer Account. Use your global user account or local user account to access this server.", "The user must change his password before he logs on the first time.", "NT_STATUS_NOT_FOUND", "The referenced account is currently locked out and may not be logged on to.", diff --git a/src/jcifs/smb/NtlmPasswordAuthentication.java.orig b/src/jcifs/smb/NtlmPasswordAuthentication.java.orig deleted file mode 100644 index 73c26e9..0000000 --- a/src/jcifs/smb/NtlmPasswordAuthentication.java.orig +++ /dev/null @@ -1,441 +0,0 @@ -/* jcifs smb client library in Java - * Copyright (C) 2002 "Michael B. Allen" - * "Eric Glass" - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -package jcifs.smb; - -import java.io.UnsupportedEncodingException; -import java.io.Serializable; -import java.security.Principal; -import java.util.Random; -import java.util.Arrays; -import jcifs.Config; -import jcifs.util.*; - -/** - * This class stores and encrypts NTLM user credentials. The default - * credentials are retrieved from the jcifs.smb.client.domain, - * jcifs.smb.client.username, and jcifs.smb.client.password - * properties. - *

- * Read jCIFS Exceptions and - * NtlmAuthenticator for related information. - */ - -public final class NtlmPasswordAuthentication implements Principal, Serializable { - - private static final int LM_COMPATIBILITY = - Config.getInt("jcifs.smb.lmCompatibility", 0); - - private static final Random RANDOM = new Random(); - - private static LogStream log = LogStream.getInstance(); - - // KGS!@#$% - private static final byte[] S8 = { - (byte)0x4b, (byte)0x47, (byte)0x53, (byte)0x21, - (byte)0x40, (byte)0x23, (byte)0x24, (byte)0x25 - }; - private static void E( byte[] key, byte[] data, byte[] e ) { - byte[] key7 = new byte[7]; - byte[] e8 = new byte[8]; - - for( int i = 0; i < key.length / 7; i++ ) { - System.arraycopy( key, i * 7, key7, 0, 7 ); - DES des = new DES( key7 ); - des.encrypt( data, e8 ); - System.arraycopy( e8, 0, e, i * 8, 8 ); - } - } - - static String DEFAULT_DOMAIN; - static String DEFAULT_USERNAME; - static String DEFAULT_PASSWORD; - static final String BLANK = ""; - - static void initDefaults() { - if (DEFAULT_DOMAIN != null) return; - DEFAULT_DOMAIN = Config.getProperty("jcifs.smb.client.domain", "?"); - DEFAULT_USERNAME = Config.getProperty("jcifs.smb.client.username", "GUEST"); - DEFAULT_PASSWORD = Config.getProperty("jcifs.smb.client.password", BLANK); - } - -/** - * Generate the ANSI DES hash for the password associated with these credentials. - */ - static public byte[] getPreNTLMResponse( String password, byte[] challenge ) { - byte[] p14 = new byte[14]; - byte[] p21 = new byte[21]; - byte[] p24 = new byte[24]; - byte[] passwordBytes; - try { - passwordBytes = password.toUpperCase().getBytes( ServerMessageBlock.OEM_ENCODING ); - } catch( UnsupportedEncodingException uee ) { - throw new RuntimeException("Try setting jcifs.encoding=US-ASCII", uee); - } - int passwordLength = passwordBytes.length; - - // Only encrypt the first 14 bytes of the password for Pre 0.12 NT LM - if( passwordLength > 14) { - passwordLength = 14; - } - System.arraycopy( passwordBytes, 0, p14, 0, passwordLength ); - E( p14, S8, p21); - E( p21, challenge, p24); - return p24; - } -/** - * Generate the Unicode MD4 hash for the password associated with these credentials. - */ - static public byte[] getNTLMResponse( String password, byte[] challenge ) { - byte[] uni = null; - byte[] p21 = new byte[21]; - byte[] p24 = new byte[24]; - - try { - uni = password.getBytes( "UnicodeLittleUnmarked" ); - } catch( UnsupportedEncodingException uee ) { - if( log.level > 0 ) - uee.printStackTrace( log ); - } - MD4 md4 = new MD4(); - md4.update( uni ); - try { - md4.digest(p21, 0, 16); - } catch (Exception ex) { - if( log.level > 0 ) - ex.printStackTrace( log ); - } - E( p21, challenge, p24 ); - return p24; - } - - /** - * Creates the LMv2 response for the supplied information. - * - * @param domain The domain in which the username exists. - * @param user The username. - * @param password The user's password. - * @param challenge The server challenge. - * @param clientChallenge The client challenge (nonce). - */ - public static byte[] getLMv2Response(String domain, String user, - String password, byte[] challenge, byte[] clientChallenge) { - try { - byte[] hash = new byte[16]; - byte[] response = new byte[24]; - MD4 md4 = new MD4(); - md4.update(password.getBytes("UnicodeLittleUnmarked")); - HMACT64 hmac = new HMACT64(md4.digest()); - hmac.update(user.toUpperCase().getBytes("UnicodeLittleUnmarked")); - hmac.update(domain.toUpperCase().getBytes("UnicodeLittleUnmarked")); - hmac = new HMACT64(hmac.digest()); - hmac.update(challenge); - hmac.update(clientChallenge); - hmac.digest(response, 0, 16); - System.arraycopy(clientChallenge, 0, response, 16, 8); - return response; - } catch (Exception ex) { - if( log.level > 0 ) - ex.printStackTrace( log ); - return null; - } - } - - static final NtlmPasswordAuthentication NULL = - new NtlmPasswordAuthentication( "", "", "" ); - static final NtlmPasswordAuthentication GUEST = - new NtlmPasswordAuthentication( "?", "GUEST", "" ); - static final NtlmPasswordAuthentication DEFAULT = - new NtlmPasswordAuthentication( null ); - - String domain; - String username; - String password; - byte[] ansiHash; - byte[] unicodeHash; - boolean hashesExternal = false; - byte[] clientChallenge = null; - byte[] challenge = null; - -/** - * Create an NtlmPasswordAuthentication object from the userinfo - * component of an SMB URL like "domain;user:pass". This constructor - * is used internally be jCIFS when parsing SMB URLs. - */ - - public NtlmPasswordAuthentication( String userInfo ) { - domain = username = password = null; - - if( userInfo != null ) { - int i, u, end; - char c; - - end = userInfo.length(); - for( i = 0, u = 0; i < end; i++ ) { - c = userInfo.charAt( i ); - if( c == ';' ) { - domain = userInfo.substring( 0, i ); - u = i + 1; - } else if( c == ':' ) { - password = userInfo.substring( i + 1 ); - break; - } - } - username = userInfo.substring( u, i ); - } - - initDefaults(); - - if( domain == null ) this.domain = DEFAULT_DOMAIN; - if( username == null ) this.username = DEFAULT_USERNAME; - if( password == null ) this.password = DEFAULT_PASSWORD; - } -/** - * Create an NtlmPasswordAuthentication object from a - * domain, username, and password. Parameters that are null - * will be substituted with jcifs.smb.client.domain, - * jcifs.smb.client.username, jcifs.smb.client.password - * property values. - */ - public NtlmPasswordAuthentication( String domain, String username, String password ) { - this.domain = domain; - this.username = username; - this.password = password; - - initDefaults(); - - if( domain == null ) this.domain = DEFAULT_DOMAIN; - if( username == null ) this.username = DEFAULT_USERNAME; - if( password == null ) this.password = DEFAULT_PASSWORD; - } -/** - * Create an NtlmPasswordAuthentication object with raw password - * hashes. This is used exclusively by the jcifs.http.NtlmSsp - * class which is in turn used by NTLM HTTP authentication functionality. - */ - public NtlmPasswordAuthentication( String domain, String username, - byte[] challenge, byte[] ansiHash, byte[] unicodeHash ) { - if( domain == null || username == null || - ansiHash == null || unicodeHash == null ) { - throw new IllegalArgumentException( "External credentials cannot be null" ); - } - this.domain = domain; - this.username = username; - this.password = null; - this.challenge = challenge; - this.ansiHash = ansiHash; - this.unicodeHash = unicodeHash; - hashesExternal = true; - } - -/** - * Returns the domain. - */ - public String getDomain() { - return domain; - } -/** - * Returns the username. - */ - public String getUsername() { - return username; - } -/** - * Returns the password in plain text or null if the raw password - * hashes were used to construct this NtlmPasswordAuthentication - * object which will be the case when NTLM HTTP Authentication is - * used. There is no way to retrieve a users password in plain text unless - * it is supplied by the user at runtime. - */ - public String getPassword() { - return password; - } -/** - * Return the domain and username in the format: - * domain\\username. This is equivalent to toString(). - */ - public String getName() { - boolean d = domain.length() > 0 && domain.equals( "?" ) == false; - return d ? domain + "\\" + username : username; - } - -/** - * Computes the 24 byte ANSI password hash given the 8 byte server challenge. - */ - public byte[] getAnsiHash( byte[] challenge ) { - if( hashesExternal ) { - return ansiHash; - } - switch (LM_COMPATIBILITY) { - case 0: - case 1: - return getPreNTLMResponse( password, challenge ); - case 2: - return getNTLMResponse( password, challenge ); - case 3: - case 4: - case 5: - if( clientChallenge == null ) { - clientChallenge = new byte[8]; - RANDOM.nextBytes( clientChallenge ); - } - return getLMv2Response(domain, username, password, challenge, - clientChallenge); - default: - return getPreNTLMResponse( password, challenge ); - } - } -/** - * Computes the 24 byte Unicode password hash given the 8 byte server challenge. - */ - public byte[] getUnicodeHash( byte[] challenge ) { - if( hashesExternal ) { - return unicodeHash; - } - switch (LM_COMPATIBILITY) { - case 0: - case 1: - case 2: - return getNTLMResponse( password, challenge ); - case 3: - case 4: - case 5: - /* - if( clientChallenge == null ) { - clientChallenge = new byte[8]; - RANDOM.nextBytes( clientChallenge ); - } - return getNTLMv2Response(domain, username, password, null, - challenge, clientChallenge); - */ - return new byte[0]; - default: - return getNTLMResponse( password, challenge ); - } - } - - /** - * Returns the effective user session key. - * - * @param challenge The server challenge. - * @return A byte[] containing the effective user session key, - * used in SMB MAC signing and NTLMSSP signing and sealing. - */ - public byte[] getUserSessionKey(byte[] challenge) { - if (hashesExternal) return null; - byte[] key = new byte[16]; - try { - getUserSessionKey(challenge, key, 0); - } catch (Exception ex) { - if( log.level > 0 ) - ex.printStackTrace( log ); - } - return key; - } - - /** - * Calculates the effective user session key. - * - * @param challenge The server challenge. - * @param dest The destination array in which the user session key will be - * placed. - * @param offset The offset in the destination array at which the - * session key will start. - */ - void getUserSessionKey(byte[] challenge, byte[] dest, int offset) - throws Exception { - if (hashesExternal) return; - MD4 md4 = new MD4(); - md4.update(password.getBytes("UnicodeLittleUnmarked")); - switch (LM_COMPATIBILITY) { - case 0: - case 1: - case 2: - md4.update(md4.digest()); - md4.digest(dest, offset, 16); - break; - case 3: - case 4: - case 5: - if( clientChallenge == null ) { - clientChallenge = new byte[8]; - RANDOM.nextBytes( clientChallenge ); - } - - HMACT64 hmac = new HMACT64(md4.digest()); - hmac.update(username.toUpperCase().getBytes( - "UnicodeLittleUnmarked")); - hmac.update(domain.toUpperCase().getBytes( - "UnicodeLittleUnmarked")); - byte[] ntlmv2Hash = hmac.digest(); - hmac = new HMACT64(ntlmv2Hash); - hmac.update(challenge); - hmac.update(clientChallenge); - HMACT64 userKey = new HMACT64(ntlmv2Hash); - userKey.update(hmac.digest()); - userKey.digest(dest, offset, 16); - break; - default: - md4.update(md4.digest()); - md4.digest(dest, offset, 16); - break; - } - } - -/** - * Compares two NtlmPasswordAuthentication objects for - * equality. Two NtlmPasswordAuthentication objects are equal if - * their caseless domain and username fields are equal and either both hashes are external and they are equal or both internally supplied passwords are equal. If one NtlmPasswordAuthentication object has external hashes (meaning negotiated via NTLM HTTP Authentication) and the other does not they will not be equal. This is technically not correct however the server 8 byte challage would be required to compute and compare the password hashes but that it not available with this method. - */ - public boolean equals( Object obj ) { - if( obj instanceof NtlmPasswordAuthentication ) { - NtlmPasswordAuthentication ntlm = (NtlmPasswordAuthentication)obj; - if( ntlm.domain.toUpperCase().equals( domain.toUpperCase() ) && - ntlm.username.toUpperCase().equals( username.toUpperCase() )) { - if( hashesExternal && ntlm.hashesExternal ) { - return Arrays.equals( ansiHash, ntlm.ansiHash ) && - Arrays.equals( unicodeHash, ntlm.unicodeHash ); - /* This still isn't quite right. If one npa object does not have external - * hashes and the other does then they will not be considered equal even - * though they may be. - */ - } else if( !hashesExternal && password.equals( ntlm.password )) { - return true; - } - } - } - return false; - } - - -/** - * Return the upcased username hash code. - */ - public int hashCode() { - return getName().toUpperCase().hashCode(); - } -/** - * Return the domain and username in the format: - * domain\\username. This is equivalent to getName(). - */ - public String toString() { - return getName(); - } -} - diff --git a/src/jcifs/smb/SmbSession.java b/src/jcifs/smb/SmbSession.java index 20f345b..1f48337 100644 --- a/src/jcifs/smb/SmbSession.java +++ b/src/jcifs/smb/SmbSession.java @@ -202,7 +202,7 @@ do { } synchronized SmbTransport transport() { if( transport == null ) { - transport = SmbTransport.getSmbTransport( address, port, localAddr, localPort ); + transport = SmbTransport.getSmbTransport( address, port, localAddr, localPort, null ); } return transport; } diff --git a/src/jcifs/smb/SmbTransport.java b/src/jcifs/smb/SmbTransport.java index be77e22..342ac47 100644 --- a/src/jcifs/smb/SmbTransport.java +++ b/src/jcifs/smb/SmbTransport.java @@ -38,10 +38,10 @@ public class SmbTransport extends Transport implements SmbConstants { static HashMap dfsRoots = null; static synchronized SmbTransport getSmbTransport( UniAddress address, int port ) { - return getSmbTransport( address, port, LADDR, LPORT ); + return getSmbTransport( address, port, LADDR, LPORT, null ); } static synchronized SmbTransport getSmbTransport( UniAddress address, int port, - InetAddress localAddr, int localPort ) { + InetAddress localAddr, int localPort, String hostName ) { SmbTransport conn; synchronized( CONNECTIONS ) { @@ -49,7 +49,7 @@ public class SmbTransport extends Transport implements SmbConstants { ListIterator iter = CONNECTIONS.listIterator(); while( iter.hasNext() ) { conn = (SmbTransport)iter.next(); - if( conn.matches( address, port, localAddr, localPort ) && + if( conn.matches( address, port, localAddr, localPort, hostName ) && ( SSN_LIMIT == 0 || conn.sessions.size() < SSN_LIMIT )) { return conn; } @@ -107,7 +107,7 @@ public class SmbTransport extends Transport implements SmbConstants { int capabilities = CAPABILITIES; int sessionKey = 0x00000000; boolean useUnicode = USE_UNICODE; - String tconHostName; + String tconHostName = null; SmbTransport( UniAddress address, int port, InetAddress localAddr, int localPort ) { this.address = address; @@ -150,8 +150,11 @@ public class SmbTransport extends Transport implements SmbConstants { return ssn; } - boolean matches( UniAddress address, int port, InetAddress localAddr, int localPort ) { - return address.equals( this.address ) && + boolean matches( UniAddress address, int port, InetAddress localAddr, int localPort, String hostName ) { + if (hostName == null) + hostName = address.getHostName(); + return (this.tconHostName == null || hostName.equalsIgnoreCase(this.tconHostName)) && + address.equals( this.address ) && (port == 0 || port == this.port || /* port 139 is ok if 445 was requested */ (port == 445 && this.port == 139)) &&