+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
<project name="jcifs" default="usage" basedir=".">
- <property name="version" value="1.3.0"/>
- <property name="reldate" value="Oct 26, 2008"/>
+ <property name="version" value="1.3.1"/>
+ <property name="reldate" value="Nov 30, 2008"/>
<target name="usage">
<echo>
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;
import jcifs.dcerpc.msrpc.*;
-class DcerpcBinding {
+public class DcerpcBinding {
private static HashMap INTERFACES;
INTERFACES.put("netdfs", netdfs.getSyntax());
}
+ public static void addInterface(String name, String syntax)
+ {
+ INTERFACES.put(name, syntax);
+ }
+
String proto;
String server;
String endpoint = null;
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)
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);
[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;
}
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; }
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);
+ }
+ }
+ }
+ }
}
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() ) {
}
}
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];
}
*/
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;
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());
}
}
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));
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) {
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,
* 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;
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 = "\\";
write( b, 0, b.length );
}
+ public boolean isOpen()
+ {
+ return file.isOpen();
+ }
void ensureOpen() throws IOException {
// ensure file is open
if( file.isOpen() == false ) {
}
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 */