cancel
Showing results for 
Search instead for 
Did you mean: 

Alfresco JLan SMB/CIFS Custom Authenticator error

sfigueras
Champ in-the-making
Champ in-the-making
Hi everyone,

I'm creating an custom authenticator to my Alfresco JLan authenticate into one specific Database.

Here's my jlanConfig.xml:

<?xml version="1.0" standalone="no"?><!– <!DOCTYPE jlanserver SYSTEM "jlanserver.dtd"> –><jlanserver>  <servers>    <SMB/>    <noFTP/>    <noNFS/>  </servers>  <SMB>    <host name="NUAGESERVER" domain="NUAGE">      <broadcast>255.255.255.0</broadcast>      <smbdialects>LanMan,NT</smbdialects>      <comment>Alfresco JLAN Server</comment>      <Win32NetBIOS/>      <Win32Announce interval="5"/>      <!– To run the server using a non-root account on linux, Mac OS X, Solaris –>        <netBIOSSMB sessionPort="1139" namePort="1137" datagramPort="1138" platforms="linux,macosx,solaris"/>      <tcpipSMB port="1445" platforms="linux,macosx,solaris"/>      <hostAnnounce interval="5"/>    </host>    <sessionDebug flags="Negotiate,Socket,Tree"/>    <netbiosDebug/>    <announceDebug/>         <authenticator>            <class>com.ye.nuage.auth.NuageAuthenticator</class>      <Debug/>        </authenticator>  </SMB>  <FTP>    <port>21</port>    <allowAnonymous/>    <debug flags="File,Search,Error,DataPort,Directory"/>  </FTP>  <NFS>    <enablePortMapper/>    <debug flags="File,FileIO"/>  </NFS>  <debug>    <output>      <class>org.alfresco.jlan.debug.ConsoleDebug</class>      <logFile>jlansrv.log</logFile>      <append/>    </output>  </debug>  <shares>    <diskshare name="JLAN" comment="Test share">      <driver>        <class>org.alfresco.jlan.smb.server.disk.JavaFileDiskDriver</class>        <LocalPath>.</LocalPath>      </driver>    </diskshare>  </shares>       <security>    <JCEProvider>cryptix.jce.provider.CryptixCrypto</JCEProvider>    <authenticator>      <class>com.ye.nuage.auth.NuageAuthenticator</class>      <mode>USER</mode>    </authenticator>    <users>      <user name="jlansrv">        <password>jlan</password>        <comment>System administrator</comment>        <administrator/>      </user>      <user name="normal">        <password>normal</password>      </user>    </users>  </security></jlanserver>‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

My NuageAuthenticator is a copy of CifsAuthenticator, excepts those methods:

Override
public int authenticateUser(ClientInfo client, SrvSession sess, int alg) {    // Check if the user exists in the user list    UserAccount userAcc = null;    try {        userAcc = getNuageUserDetails(client.getUserName());    } catch (YeException e) {        e.printStackTrace();    }    if (userAcc != null) {        // Validate the password        boolean authSts = false;        if (client.getPassword() != null) {            // Validate using the Unicode password            authSts = validateNuagePassword(userAcc, client, sess.getAuthenticationContext(), alg);        } else if (client.hasANSIPassword()) {            // Validate using the ANSI password with the LanMan encryption            authSts = validateNuagePassword(userAcc, client, sess.getAuthenticationContext(), LANMAN);        }        // Return the authentication status        return authSts == true ? AUTH_ALLOW : AUTH_BADPASSWORD;    }    // Check if this is an SMB/CIFS null session logon.    //    // The null session will only be allowed to connect to the IPC$ named    // pipe share.    if (client.isNullSession() && sess instanceof SMBSrvSession)        return AUTH_ALLOW;    // Unknown user    return allowGuest() ? AUTH_GUEST : AUTH_DISALLOW;}private UserAccount getNuageUserDetails(String userName) throws YeException {    if (context == null) {        context = new ClassPathXmlApplicationContext("/applicationContext-nuage.xml");    }    userRepository = context.getBean(UserRepository.class);    User u = userRepository.findByUserLogin(userName); // Search the user into my repository    if (u != null) {        UserAccount ua = new UserAccount();        ua.setMD4Password(u.getUserMd4Password().getBytes());        ua.setUserName(userName);        ua.setRealName(u.getUserFirstName() + " " + u.getUserLastName());        return ua;    }    return null;}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

But when I try to login, I receive the following error when I'm calling the validatePassword method.

 
  [T2] Closing session due to exceptionjava.lang.ArrayIndexOutOfBoundsException    at java.lang.System.arraycopy(Native Method)    at com.ye.nuage.auth.NuageAuthenticator.validatePassword(NuageAuthenticator.java:123)    at com.ye.nuage.auth.NuageAuthenticator.authenticateUser(NuageAuthenticator.java:60)    at org.alfresco.jlan.server.auth.CifsAuthenticator.processSessionSetup(CifsAuthenticator.java:572)    at org.alfresco.jlan.smb.server.NTProtocolHandler.procSessionSetup(NTProtocolHandler.java:396)    at org.alfresco.jlan.smb.server.NTProtocolHandler.runProtocol(NTProtocolHandler.java:213)    at org.alfresco.jlan.smb.server.SMBSrvSession.processPacket(SMBSrvSession.java:1439)    at org.alfresco.jlan.smb.server.nio.NIOCIFSThreadRequest.runRequest(NIOCIFSThreadRequest.java:104)    at org.alfresco.jlan.server.thread.ThreadRequestPool$ThreadWorker.run(ThreadRequestPool.java:141)    at java.lang.Thread.run(Thread.java:722)java.lang.ArrayIndexOutOfBoundsException    at java.lang.System.arraycopy(Native Method)    at com.ye.nuage.auth.NuageAuthenticator.validatePassword(NuageAuthenticator.java:123)    at com.ye.nuage.auth.NuageAuthenticator.authenticateUser(NuageAuthenticator.java:60)    at org.alfresco.jlan.server.auth.CifsAuthenticator.processSessionSetup(CifsAuthenticator.java:572)    at org.alfresco.jlan.smb.server.NTProtocolHandler.procSessionSetup(NTProtocolHandler.java:396)    at org.alfresco.jlan.smb.server.NTProtocolHandler.runProtocol(NTProtocolHandler.java:213)    at org.alfresco.jlan.smb.server.SMBSrvSession.processPacket(SMBSrvSession.java:1439)    at org.alfresco.jlan.smb.server.nio.NIOCIFSThreadRequest.runRequest(NIOCIFSThreadRequest.java:104)    at org.alfresco.jlan.server.thread.ThreadRequestPool$ThreadWorker.run(ThreadRequestPool.java:141)    at java.lang.Thread.run(Thread.java:722)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Here's a method snip:

if (user.hasMD4Password() && alg != LANMAN) {            try {                // Generate the encrpyted password                if (alg == NTLM1) {                    // Get the MD4 hashed password                    byte[] p21 = new byte[21];                    System.arraycopy(user.getMD4Password(), 0, p21, 0, user.getMD4Password().length); **//THE ERROR OCCURS HERE!**                    // Generate an NTLMv1 encrypted password‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

The error occurs here:

System.arraycopy(user.getMD4Password(), 0, p21, 0, user.getMD4Password().length); ‍‍‍


But the question is very simple: Why this error occurs? Some mismatch between the MD4 hashes? Is that possible?
6 REPLIES 6

mrogers
Star Contributor
Star Contributor
it would appear from the error message that the destination array is too small.   Why are you hard coding a length of 21?   Rather than using the correct length?

sfigueras
Champ in-the-making
Champ in-the-making
Hi mrogers,

That code is from CifsAuthenticator, from Alfresco. That's the same code.It's not my modification. Here's the original from Alfresco: http://fossies.org/linux/misc/dsnet-src-1.1.0.zip:t/dsnet-src-1.1.0/filedevice-org/source/java/org/a...

mrogers
Star Contributor
Star Contributor
The 21 comes from the specs for NTLMV1. So although I don't like that code and clearly there is a need for more javadoc it may not be a serious bug.  

Nevertheless it looks like there is something different going on with your getMD4Password() method that is returning too many bytes.  Perhaps its a padding issue?    The MD4 hash should probably be 16 bytes.  Which then gets padded out to 21.

sfigueras
Champ in-the-making
Champ in-the-making
Hi mrogers,

Thanks for the reply. That's my "admin" string md4 hash, generated by my Spring md4 encryptor:

String md4Password = md4PasswordEncoder.encodePassword("admin", null);‍‍‍


It results in
f9d4049dd6a4dc35d40e5265954b2a46‍‍‍


Is that the correct way to generate my MD4 hash to use with NTLM?

If you want, here you can see the md4PasswordEncoder source: http://www.jarvana.com/jarvana/view/org/springframework/security/spring-security-core/3.0.3.RELEASE/...

Thanks! Smiley Happy

mrogers
Star Contributor
Star Contributor
That is a 32 byte hash.  Its too big for NTLMV1  

http://en.wikipedia.org/wiki/NTLM

sfigueras
Champ in-the-making
Champ in-the-making
Hi mrogers,

Again, thanks for your reply. But I think that I've discovered a bug into Alfresco JLan 5.0.

To test that problem, I've implemented an UserInterface class as you  can see below:

public UserAccount getUserAccount(String userName) {      if (userName.equals("admin")) {         cryptoutils cu = new cryptoutils();         byte[] md4 = null;         try {            md4 = cu.generateEncryptedPassword("admin", null, PasswordEncryptor.MD4, null, null);         } catch (Exception e) {            e.printStackTrace();         }         UserAccount ua = new UserAccount();         ua.setUserName("admin");         ua.setMD4Password(md4);         ua.setPassword("admin");         return ua;      }      return null;   }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍


Ok, that was ok, now that error was resolved, but, other problem is occurring.

If i try to login with my Linux workstation, with this shell code:

smbclient -L localhost -U admin -W NUAGE‍


The authentication stops on CifsAuthenticator.validateNuagePassword, on that line:

if (encPwd != null && encryptedPwd != null && encPwd.length == STANDARD_PASSWORD_LEN && encryptedPwd.length == STANDARD_PASSWORD_LEN) {‍


Because the encryptedPwd variable length is bigger than STANDARD_PASSWORD_LEN (24).

But, if I try to login with one Windows Desktop, everything goes ok, and encryptedPwd stay with 24 positions.
Welcome to the new Hyland Connect. Get started or submit feedback.