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 exception
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)
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.