From 047cb01e4766b97f8e89ae2a8c5f16fb3a71d8ca Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Mon, 1 Dec 2008 08:47:51 +0100 Subject: [PATCH] jcifs-1.3.1 from tgz Sat Nov 30 00:32:09 EST 2008 jcifs-1.3.1 The NtlmPasswordAuthentication constructor has been modified to canonicalize the username from DOMAIN\username or username@domain to username and set the domain separately. The getNTLMv2Response method has been adjusted to permit the targetInfo to be null. Minor changes to DFS have been applied that claim to prevent errors in certain DFS scenarios. The NTLM HTTP Filter was broken in 1.3.0. Turning off useExtendedSecurity reportedly fixes the issue. Note: The semantics of the fourth parameter of getNTLMv2Response has changed. --- README.txt | 19 ++++++ build.xml | 4 +- examples/AuthListFiles.java | 13 ++-- src/jcifs/dcerpc/DcerpcBinding.java | 7 +- src/jcifs/dcerpc/DcerpcPipeHandle.java | 3 + src/jcifs/dcerpc/msrpc/samr.idl | 40 ++++++++++++ src/jcifs/dcerpc/msrpc/samr.java | 92 +++++++++++++++++++++++++++ src/jcifs/http/NtlmHttpFilter.java | 5 +- src/jcifs/ntlmssp/Type2Message.java | 2 +- src/jcifs/ntlmssp/Type3Message.java | 12 ++-- src/jcifs/smb/Dfs.java | 10 +-- src/jcifs/smb/NtlmPasswordAuthentication.java | 25 ++++++-- src/jcifs/smb/SmbFile.java | 8 +++ src/jcifs/smb/SmbFileOutputStream.java | 4 ++ src/jcifs/smb/SmbTransport.java | 6 ++ 15 files changed, 220 insertions(+), 30 deletions(-) diff --git a/README.txt b/README.txt index 8ae86df..52826a9 100644 --- a/README.txt +++ b/README.txt @@ -1,3 +1,22 @@ +Sat Nov 30 00:32:09 EST 2008 +jcifs-1.3.1 + +The NtlmPasswordAuthentication constructor has been modified to +canonicalize the username from DOMAIN\username or username@domain to +username and set the domain separately. + +The getNTLMv2Response method has been adjusted to permit the targetInfo +to be null. + +Minor changes to DFS have been applied that claim to prevent errors in +certain DFS scenarios. + +The NTLM HTTP Filter was broken in 1.3.0. Turning off useExtendedSecurity +reportedly fixes the issue. + +Note: The semantics of the fourth parameter of getNTLMv2Response has +changed. + Sat Oct 25 17:45:51 EDT 2008 jcifs-1.3.0 released diff --git a/build.xml b/build.xml index 3d1a159..1efcea8 100644 --- a/build.xml +++ b/build.xml @@ -1,7 +1,7 @@ - - + + diff --git a/examples/AuthListFiles.java b/examples/AuthListFiles.java index 9958fad..9fb1b1e 100644 --- a/examples/AuthListFiles.java +++ b/examples/AuthListFiles.java @@ -30,22 +30,17 @@ public class AuthListFiles extends NtlmAuthenticator { protected NtlmPasswordAuthentication getNtlmPasswordAuthentication() { System.out.println( getRequestingException().getMessage() + " for " + getRequestingURL() ); - System.out.print( "username: " ); try { - int i; + System.out.print( "username: " ); String username = readLine(); - String domain = null, password; - if(( i = username.indexOf( '\\' )) != -1 ) { - domain = username.substring( 0, i ); - username = username.substring( i + 1 ); - } System.out.print( "password: " ); - password = readLine(); + String password = readLine(); + if( password.length() == 0 ) { return null; } - return new NtlmPasswordAuthentication( domain, username, password ); + return new NtlmPasswordAuthentication( null, username, password ); } catch( Exception e ) { } return null; diff --git a/src/jcifs/dcerpc/DcerpcBinding.java b/src/jcifs/dcerpc/DcerpcBinding.java index 77b635b..42a568e 100644 --- a/src/jcifs/dcerpc/DcerpcBinding.java +++ b/src/jcifs/dcerpc/DcerpcBinding.java @@ -24,7 +24,7 @@ import java.util.Iterator; import jcifs.dcerpc.msrpc.*; -class DcerpcBinding { +public class DcerpcBinding { private static HashMap INTERFACES; @@ -36,6 +36,11 @@ class DcerpcBinding { INTERFACES.put("netdfs", netdfs.getSyntax()); } + public static void addInterface(String name, String syntax) + { + INTERFACES.put(name, syntax); + } + String proto; String server; String endpoint = null; diff --git a/src/jcifs/dcerpc/DcerpcPipeHandle.java b/src/jcifs/dcerpc/DcerpcPipeHandle.java index 6be7f8c..f298341 100644 --- a/src/jcifs/dcerpc/DcerpcPipeHandle.java +++ b/src/jcifs/dcerpc/DcerpcPipeHandle.java @@ -48,6 +48,9 @@ public class DcerpcPipeHandle extends DcerpcHandle { int off, int length, boolean isDirect) throws IOException { + if (out != null && out.isOpen() == false) + throw new IOException("DCERPC pipe is no longer open"); + if (in == null) in = (SmbFileInputStream)pipe.getNamedPipeInputStream(); if (out == null) diff --git a/src/jcifs/dcerpc/msrpc/samr.idl b/src/jcifs/dcerpc/msrpc/samr.idl index 9204327..7ebb91e 100644 --- a/src/jcifs/dcerpc/msrpc/samr.idl +++ b/src/jcifs/dcerpc/msrpc/samr.idl @@ -7,6 +7,26 @@ interface samr import "../rpc.idl"; import "lsarpc.idl"; + typedef [v1_enum] enum { + ACB_DISABLED = 0x00000001, /* 1 = User account disabled */ + ACB_HOMDIRREQ = 0x00000002, /* 1 = Home directory required */ + ACB_PWNOTREQ = 0x00000004, /* 1 = User password not required */ + ACB_TEMPDUP = 0x00000008, /* 1 = Temporary duplicate account */ + ACB_NORMAL = 0x00000010, /* 1 = Normal user account */ + ACB_MNS = 0x00000020, /* 1 = MNS logon user account */ + ACB_DOMTRUST = 0x00000040, /* 1 = Interdomain trust account */ + ACB_WSTRUST = 0x00000080, /* 1 = Workstation trust account */ + ACB_SVRTRUST = 0x00000100, /* 1 = Server trust account */ + ACB_PWNOEXP = 0x00000200, /* 1 = User password does not expire */ + ACB_AUTOLOCK = 0x00000400, /* 1 = Account auto locked */ + ACB_ENC_TXT_PWD_ALLOWED = 0x00000800, /* 1 = Encryped text password is allowed */ + ACB_SMARTCARD_REQUIRED = 0x00001000, /* 1 = Smart Card required */ + ACB_TRUSTED_FOR_DELEGATION = 0x00002000, /* 1 = Trusted for Delegation */ + ACB_NOT_DELEGATED = 0x00004000, /* 1 = Not delegated */ + ACB_USE_DES_KEY_ONLY = 0x00008000, /* 1 = Use DES key only */ + ACB_DONT_REQUIRE_PREAUTH = 0x00010000 /* 1 = Preauth not required */ + } SamrAcctFlags; + [op(0x01)] int SamrCloseHandle([in] policy_handle *handle); @@ -53,4 +73,24 @@ interface samr [op(0x21)] int SamrGetMembersInAlias([in] policy_handle *alias_handle, [out] LsarSidArray *sids); + + typedef [v1_enum] enum { + SE_GROUP_MANDATORY = 0x00000001, + SE_GROUP_ENABLED_BY_DEFAULT = 0x00000002, + SE_GROUP_ENABLED = 0x00000004, + SE_GROUP_OWNER = 0x00000008, + SE_GROUP_USE_FOR_DENY_ONLY = 0x00000010, + SE_GROUP_RESOURCE = 0x20000000, + SE_GROUP_LOGON_ID = 0xC0000000 + } SamrGroupAttrs; + + typedef struct { + uint32_t rid; + SamrGroupAttrs attributes; + } SamrRidWithAttribute; + + typedef struct { + uint32_t count; + [size_is(count)] SamrRidWithAttribute *rids; + } SamrRidWithAttributeArray; } diff --git a/src/jcifs/dcerpc/msrpc/samr.java b/src/jcifs/dcerpc/msrpc/samr.java index 99fd5fe..c42c890 100644 --- a/src/jcifs/dcerpc/msrpc/samr.java +++ b/src/jcifs/dcerpc/msrpc/samr.java @@ -9,6 +9,24 @@ public class samr { return "12345778-1234-abcd-ef00-0123456789ac:1.0"; } + public static final int ACB_DISABLED = 1; + public static final int ACB_HOMDIRREQ = 2; + public static final int ACB_PWNOTREQ = 4; + public static final int ACB_TEMPDUP = 8; + public static final int ACB_NORMAL = 16; + public static final int ACB_MNS = 32; + public static final int ACB_DOMTRUST = 64; + public static final int ACB_WSTRUST = 128; + public static final int ACB_SVRTRUST = 256; + public static final int ACB_PWNOEXP = 512; + public static final int ACB_AUTOLOCK = 1024; + public static final int ACB_ENC_TXT_PWD_ALLOWED = 2048; + public static final int ACB_SMARTCARD_REQUIRED = 4096; + public static final int ACB_TRUSTED_FOR_DELEGATION = 8192; + public static final int ACB_NOT_DELEGATED = 16384; + public static final int ACB_USE_DES_KEY_ONLY = 32768; + public static final int ACB_DONT_REQUIRE_PREAUTH = 65536; + public static class SamrCloseHandle extends DcerpcMessage { public int getOpnum() { return 0x01; } @@ -318,4 +336,78 @@ public class samr { retval = (int)_src.dec_ndr_long(); } } + public static final int SE_GROUP_MANDATORY = 1; + public static final int SE_GROUP_ENABLED_BY_DEFAULT = 2; + public static final int SE_GROUP_ENABLED = 4; + public static final int SE_GROUP_OWNER = 8; + public static final int SE_GROUP_USE_FOR_DENY_ONLY = 16; + public static final int SE_GROUP_RESOURCE = 536870912; + public static final int SE_GROUP_LOGON_ID = -1073741824; + + public static class SamrRidWithAttribute extends NdrObject { + + public int rid; + public int attributes; + + public void encode(NdrBuffer _dst) throws NdrException { + _dst.align(4); + _dst.enc_ndr_long(rid); + _dst.enc_ndr_long(attributes); + + } + public void decode(NdrBuffer _src) throws NdrException { + _src.align(4); + rid = (int)_src.dec_ndr_long(); + attributes = (int)_src.dec_ndr_long(); + + } + } + public static class SamrRidWithAttributeArray extends NdrObject { + + public int count; + public SamrRidWithAttribute[] rids; + + public void encode(NdrBuffer _dst) throws NdrException { + _dst.align(4); + _dst.enc_ndr_long(count); + _dst.enc_ndr_referent(rids, 1); + + if (rids != null) { + _dst = _dst.deferred; + int _ridss = count; + _dst.enc_ndr_long(_ridss); + int _ridsi = _dst.index; + _dst.advance(8 * _ridss); + + _dst = _dst.derive(_ridsi); + for (int _i = 0; _i < _ridss; _i++) { + rids[_i].encode(_dst); + } + } + } + public void decode(NdrBuffer _src) throws NdrException { + _src.align(4); + count = (int)_src.dec_ndr_long(); + int _ridsp = _src.dec_ndr_long(); + + if (_ridsp != 0) { + _src = _src.deferred; + int _ridss = _src.dec_ndr_long(); + int _ridsi = _src.index; + _src.advance(8 * _ridss); + + if (rids == null) { + if (_ridss < 0 || _ridss > 0xFFFF) throw new NdrException( NdrException.INVALID_CONFORMANCE ); + rids = new SamrRidWithAttribute[_ridss]; + } + _src = _src.derive(_ridsi); + for (int _i = 0; _i < _ridss; _i++) { + if (rids[_i] == null) { + rids[_i] = new SamrRidWithAttribute(); + } + rids[_i].decode(_src); + } + } + } + } } diff --git a/src/jcifs/http/NtlmHttpFilter.java b/src/jcifs/http/NtlmHttpFilter.java index d4a5b28..361ac66 100644 --- a/src/jcifs/http/NtlmHttpFilter.java +++ b/src/jcifs/http/NtlmHttpFilter.java @@ -66,10 +66,11 @@ public class NtlmHttpFilter implements Filter { Config.setProperty( "jcifs.netbios.cachePolicy", "1200" ); /* The Filter can only work with NTLMv1 as it uses a man-in-the-middle * techinque that NTLMv2 specifically thwarts. A real NTLM Filter would - * need to do a NETLOGON RPC or possibly some kind of Kerberos based digest - * authentication like Hiemdal supposedly has. + * need to do a NETLOGON RPC that JCIFS will likely never implement + * because it requires a lot of extra crypto not used by CIFS. */ Config.setProperty( "jcifs.smb.lmCompatibility", "0" ); + Config.setProperty( "jcifs.smb.client.useExtendedSecurity", "false" ); Enumeration e = filterConfig.getInitParameterNames(); while( e.hasMoreElements() ) { diff --git a/src/jcifs/ntlmssp/Type2Message.java b/src/jcifs/ntlmssp/Type2Message.java index 1d92957..bc67faf 100644 --- a/src/jcifs/ntlmssp/Type2Message.java +++ b/src/jcifs/ntlmssp/Type2Message.java @@ -245,7 +245,7 @@ public class Type2Message extends NtlmMessage { } } if (targetInformation != null) { - flags ^= NTLMSSP_NEGOTIATE_TARGET_INFO; + flags |= NTLMSSP_NEGOTIATE_TARGET_INFO; // empty context is needed for padding when t.i. is supplied. if (context == null) context = new byte[8]; } diff --git a/src/jcifs/ntlmssp/Type3Message.java b/src/jcifs/ntlmssp/Type3Message.java index 5ad1b22..b548e9a 100644 --- a/src/jcifs/ntlmssp/Type3Message.java +++ b/src/jcifs/ntlmssp/Type3Message.java @@ -41,6 +41,8 @@ import jcifs.util.MD4; */ public class Type3Message extends NtlmMessage { + static final long MILLISECONDS_BETWEEN_1970_AND_1601 = 11644473600000L; + private static final int DEFAULT_FLAGS; private static final String DEFAULT_DOMAIN; @@ -581,10 +583,11 @@ public class Type3Message extends NtlmMessage { if (type2 == null || responseKeyNT == null || clientChallenge == null) { return null; } + long nanos1601 = (System.currentTimeMillis() + MILLISECONDS_BETWEEN_1970_AND_1601) * 10000L; return NtlmPasswordAuthentication.getNTLMv2Response(responseKeyNT, type2.getChallenge(), clientChallenge, - System.currentTimeMillis(), + nanos1601, type2.getTargetInformation()); } @@ -672,12 +675,7 @@ public class Type3Message extends NtlmMessage { } setFlags(flags); setLMResponse(lmResponse); - /* NTLMv2 issues w/cross-domain authentication; leave - * NT empty if NTLMv2 was sent by the client. NTLM response - * will always be 24 bytes; NTLMv2 response will always be - * longer. - Kevin Tapperson - */ - if (ntResponse.length == 24) setNTResponse(ntResponse); + setNTResponse(ntResponse); setDomain(new String(domain, charset)); setUser(new String(user, charset)); setWorkstation(new String(workstation, charset)); diff --git a/src/jcifs/smb/Dfs.java b/src/jcifs/smb/Dfs.java index 5778981..c9ff674 100644 --- a/src/jcifs/smb/Dfs.java +++ b/src/jcifs/smb/Dfs.java @@ -177,10 +177,12 @@ public class Dfs { if (links != null) { String link = "\\"; - if (path != null) { - int i = path.indexOf("\\", 1); - link = i > 0 ? path.substring(1, i) : path.substring(1); - } +/* Nov 12, 2008: liuqiang from rst.ricoh.com claims this breaks domain based dfs + * if (path != null) { + * int i = path.indexOf("\\", 1); + * link = i > 0 ? path.substring(1, i) : path.substring(1); + * } + */ dr = (DfsReferral)links.map.get(link); if (dr != null && now > dr.expiration) { diff --git a/src/jcifs/smb/NtlmPasswordAuthentication.java b/src/jcifs/smb/NtlmPasswordAuthentication.java index fddff77..125f1c4 100644 --- a/src/jcifs/smb/NtlmPasswordAuthentication.java +++ b/src/jcifs/smb/NtlmPasswordAuthentication.java @@ -240,17 +240,20 @@ public final class NtlmPasswordAuthentication implements Principal, Serializable byte[] responseKeyNT, byte[] serverChallenge, byte[] clientChallenge, - long time, + long nanos1601, byte[] targetInfo) { - byte[] temp = new byte[28 + targetInfo.length]; + int targetInfoLength = targetInfo != null ? targetInfo.length : 0; + byte[] temp = new byte[28 + targetInfoLength + 4]; Encdec.enc_uint32le(0x00000101, temp, 0); // Header Encdec.enc_uint32le(0x00000000, temp, 4); // Reserved - Encdec.enc_uint64le((time + SmbConstants.MILLISECONDS_BETWEEN_1970_AND_1601) * 10000L, temp, 8); + Encdec.enc_uint64le(nanos1601, temp, 8); System.arraycopy(clientChallenge, 0, temp, 16, 8); Encdec.enc_uint32le(0x00000000, temp, 24); // Unknown - System.arraycopy(targetInfo, 0, temp, 28, targetInfo.length); + if (targetInfo != null) + System.arraycopy(targetInfo, 0, temp, 28, targetInfoLength); + Encdec.enc_uint32le(0x00000000, temp, 28 + targetInfoLength); // mystery bytes! return NtlmPasswordAuthentication.computeResponse(responseKeyNT, serverChallenge, @@ -320,6 +323,20 @@ public final class NtlmPasswordAuthentication implements Principal, Serializable * property values. */ public NtlmPasswordAuthentication( String domain, String username, String password ) { + int ci; + + ci = username.indexOf('@'); + if (ci > 0) { + domain = username.substring(ci + 1); + username = username.substring(0, ci); + } else { + ci = username.indexOf('\\'); + if (ci > 0) { + domain = username.substring(0, ci); + username = username.substring(ci + 1); + } + } + this.domain = domain; this.username = username; this.password = password; diff --git a/src/jcifs/smb/SmbFile.java b/src/jcifs/smb/SmbFile.java index 11df2b7..5d4d4a8 100644 --- a/src/jcifs/smb/SmbFile.java +++ b/src/jcifs/smb/SmbFile.java @@ -686,6 +686,14 @@ public class SmbFile extends URLConnection implements SmbConstants { log.println( dr ); dfsReferral = dr; + /* Nov 12, 2008: liuqiang from rst.ricoh.com claims these two + * clauses are ncessary to prevent exceptions + */ + if (dr.pathConsumed < 0) { + dr.pathConsumed =0 ; + } else if (dr.pathConsumed > unc.length()) { + dr.pathConsumed = unc.length(); + } String dunc = unc.substring(dr.pathConsumed); if (dunc.equals("")) dunc = "\\"; diff --git a/src/jcifs/smb/SmbFileOutputStream.java b/src/jcifs/smb/SmbFileOutputStream.java index ccf6800..4dc9004 100644 --- a/src/jcifs/smb/SmbFileOutputStream.java +++ b/src/jcifs/smb/SmbFileOutputStream.java @@ -187,6 +187,10 @@ write, and/or delete the file while the jCIFS user has the file open. write( b, 0, b.length ); } + public boolean isOpen() + { + return file.isOpen(); + } void ensureOpen() throws IOException { // ensure file is open if( file.isOpen() == false ) { diff --git a/src/jcifs/smb/SmbTransport.java b/src/jcifs/smb/SmbTransport.java index 6677656..b1ee4e1 100644 --- a/src/jcifs/smb/SmbTransport.java +++ b/src/jcifs/smb/SmbTransport.java @@ -526,6 +526,12 @@ public class SmbTransport extends Transport implements SmbConstants { } DfsReferral[] drs = getDfsReferrals(req.auth, req.path, 1); + if (0 == drs.length) { + /* Nov 12, 2008: liuqiang from rst.ricoh.com claims this + * stops AIOBE in certain cases. + */ + throw new SmbException(resp.errorCode, null); + } SmbFile.dfs.insert(req.path, drs[0]); throw drs[0]; case 0x80000005: /* STATUS_BUFFER_OVERFLOW */ -- 2.11.0