AnsweredAssumed Answered

[CIFS] Kerberos authentication doesn't start, but try NTLM

Question asked by diegop on Oct 27, 2008
Latest reply on Nov 19, 2008 by diegop
Hi,
i'm working on Alfresco 2.1 Community Edition.

My Alfresco installation has to authenticate every user through a Single-Sign-On mechanism in a Kerberos' Realm of a Windows Domain.

I have several problems to authenticate users of my domain when try to connect to CIFS server.

I followed this procedure meticulously:

http://wiki.alfresco.com/wiki/Configuring_the_CIFS_and_web_servers_for_Kerberos/AD_integration

installing Alfresco on my PC with Windows XP and it seemed to work.

The problems are born when I installed Alfresco on a test PC with Windows 2003 Server Edition.

Sometimes, when I try to connect to CIFS server, i have to wait several seconds before that appears a dialog where I have to put a user and a password to authenticate to CIFS through a NTLM authentication, but this dialog should not appear! The user logged should have to be automatically authenticated through Kerberos.

I debugged Alfresco and sniffed the smb packets by Wireshark and I noticed that when a kerberos authentication to have to start the object NegTokenInit  negToken, defined in the method doSpnegoSessionSetup of the class EnterpriseCifsAuthenticator has three OID (Object Identifiers) in this order: [OID.ID_KERBEROS5, OID.ID_MSKERBEROS5, OID.ID_NTLMSSP].

If (incorrectly) the CIFS server request a NTLM authentication i noticed that the negToken object described above has ONLY  one OID: [OID.ID_NTLMSSP].

So, what is the problem? Who set the wrong OID list read in the doSpnegoSessionSetup method? And why? How to resolve all this?

I put the code of the method doSpnegoSessionSetup of the class EnterpriseCifsAuthenticator:

    /**
     * Process an SPNEGO security blob
     *
     * @param sess SMBSrvSession
     * @param client ClientInfo
     * @param secbuf byte[]
     * @param secpos int
     * @param seclen int
     * @param unicode boolean
     * @exception SMBSrvException
     */
    private final byte[] doSpnegoSessionSetup( SMBSrvSession sess, ClientInfo client,
            byte[] secbuf, int secpos, int seclen, boolean unicode) throws SMBSrvException
    {
        //  Check the received token type, if it is a target token and there is a stored session setup object, this is the second
        //  stage of an NTLMSSP session setup that is wrapped with SPNEGO

        int tokType = -1;
       
        try
        {
            tokType = SPNEGO.checkTokenType( secbuf, secpos, seclen);
        }
        catch ( IOException ex)
        {
        }

        //  Check for the second stage of an NTLMSSP logon
       
        NegTokenTarg negTarg = null;
       
        if ( tokType == SPNEGO.NegTokenTarg && sess.hasSetupObject( client.getProcessId()) && sess.getSetupObject( client.getProcessId()) instanceof Type2NTLMMessage)
        {
            //  Get the NTLMSSP blob from the NegTokenTarg blob
           
            NegTokenTarg negToken = new NegTokenTarg();
           
            try
            {
                // Decode the security blob
               
                negToken.decode( secbuf, secpos, seclen);
            }
            catch ( IOException ex)
            {
                // Log the error
               
                logger.error(ex);
               
                // Return a logon failure status
               
                throw new SMBSrvException( SMBStatus.NTLogonFailure, SMBStatus.DOSAccessDenied, SMBStatus.ErrDos);
            }

            //  Get the second stage NTLMSSP blob
           
            byte[] ntlmsspBlob = negToken.getResponseToken();

            //  Perform an NTLMSSP session setup
           
            byte[] ntlmsspRespBlob = doNtlmsspSessionSetup( sess, client, ntlmsspBlob, 0, ntlmsspBlob.length, unicode);
           
            //  NTLMSSP is a two stage process, set the SPNEGO status
           
            int spnegoSts = SPNEGO.AcceptCompleted;
           
            if ( sess.hasSetupObject( client.getProcessId()))
                spnegoSts = SPNEGO.AcceptIncomplete;
           
            //  Package the NTLMSSP response in an SPNEGO response

            negTarg = new NegTokenTarg( spnegoSts, null, ntlmsspRespBlob);
        }
        else if ( tokType == SPNEGO.NegTokenInit)
        {
            //  Parse the SPNEGO security blob to get the Kerberos ticket
           
            NegTokenInit negToken = new NegTokenInit();
           
            try
            {
                // Decode the security blob
               
                negToken.decode( secbuf, secpos, seclen);
            }
            catch ( IOException ex)
            {
                // Log the error
               
                logger.error(ex);
               
                // Return a logon failure status
               
                throw new SMBSrvException( SMBStatus.NTLogonFailure, SMBStatus.DOSAccessDenied, SMBStatus.ErrDos);
            }
   
            //  Determine the authentication mechanism the client is using and logon
           
            String oidStr = null;
            if ( negToken.numberOfOids() > 0)
                oidStr = negToken.getOidAt( 0).toString();
           
            if ( oidStr != null && oidStr.equals( OID.ID_NTLMSSP))
            {
                //  NTLMSSP logon, get the NTLMSSP security blob that is inside the SPNEGO blob
               
                byte[] ntlmsspBlob = negToken.getMechtoken();
   
                //  Perform an NTLMSSP session setup
               
                byte[] ntlmsspRespBlob = doNtlmsspSessionSetup( sess, client, ntlmsspBlob, 0, ntlmsspBlob.length, unicode);
               
                //  NTLMSSP is a two stage process, set the SPNEGO status
               
                int spnegoSts = SPNEGO.AcceptCompleted;
               
                if ( sess.hasSetupObject( client.getProcessId()))
                    spnegoSts = SPNEGO.AcceptIncomplete;
               
                //  Package the NTLMSSP response in an SPNEGO response
   
                negTarg = new NegTokenTarg( spnegoSts, OID.NTLMSSP, ntlmsspRespBlob);
            }
            else if (  oidStr != null && (oidStr.equals( OID.ID_MSKERBEROS5) || oidStr.equals(OID.ID_KERBEROS5)))
            {
                //  Kerberos logon
               
                negTarg = doKerberosLogon( sess, negToken, client);
            }
            else
            {
                //  Debug
               
                if ( logger.isDebugEnabled())
                {
                    logger.debug("No matching authentication OID found");
                    logger.debug("  " + negToken.toString());
                }
                   
                //  No valid authentication mechanism
               
                throw new SMBSrvException( SMBStatus.NTLogonFailure, SMBStatus.DOSAccessDenied, SMBStatus.ErrDos);
            }
        }
        else
        {
            //  Unknown SPNEGO token type
           
            logger.error( "Unknown SPNEGO token type");
           
            // Return a logon failure status
           
            throw new SMBSrvException( SMBStatus.NTLogonFailure, SMBStatus.DOSAccessDenied, SMBStatus.ErrDos);
        }
       
        // Generate the NegTokenTarg blob

        byte[] respBlob = null;
       
        try
        {
            // Generate the response blob
           
           respBlob = negTarg.encode();
        }
        catch ( IOException ex)
        {
            //  Debug
           
            if ( logger.isDebugEnabled())
                logger.debug("Failed to encode NegTokenTarg", ex);

            //  Failed to build response blob
           
            throw new SMBSrvException( SMBStatus.NTLogonFailure, SMBStatus.DOSAccessDenied, SMBStatus.ErrDos);
        }
       
        //  Return the SPNEGO response blob
       
        return respBlob;
    }

After read this page:

http://wiki.alfresco.com/wiki/Enterprise_Security_and_Authentication_Configuration

I know that Alfresco CIFS SSO is possible only with Enterprise Authenticator  with Kerberos. Isn't it?

P.S. Alfresco runs on a Windows 2003 Server (on a Tomcat), while every client has a Windows XP or Windows 2003 Server, could be an Active Directory settings problem?

Outcomes