From e184c83df56c9693401e7c99e5534034f4f51d8f Mon Sep 17 00:00:00 2001 From: Dave Ward Date: Wed, 26 Aug 2009 19:15:18 +0000 Subject: [PATCH] Merged V3.2 to HEAD 15940: Merged V3.1 to V3.2 (record only) 15939: Merged V3.2 to V3.1 15936: ETHREEOH-2498: Fixed problems with auto-creation of users in CIFS Authenticators (including Kerberos) 15936: ETHREEOH-2498: Fixed problems with auto-creation of users in CIFS Authenticators (including Kerberos) - Converted to using RetryingTransactionHelper and avoid problems with nested transactionService - Will trigger LDAP sync if enabled - Also switched on disableNTLM in kerberos-authentication-context.xml to force Kerberos CIFS authentication in Kerberos subsystem git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@15941 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../kerberos-authentication-context.xml | 3 + .../auth/cifs/AlfrescoCifsAuthenticator.java | 65 +-- .../auth/cifs/CifsAuthenticatorBase.java | 189 +++---- .../cifs/EnterpriseCifsAuthenticator.java | 159 ++---- .../auth/cifs/PassthruCifsAuthenticator.java | 491 ++++++++---------- 5 files changed, 360 insertions(+), 547 deletions(-) diff --git a/config/alfresco/subsystems/Authentication/kerberos/kerberos-authentication-context.xml b/config/alfresco/subsystems/Authentication/kerberos/kerberos-authentication-context.xml index 9fd0d41ffd..66bbc2b2fe 100644 --- a/config/alfresco/subsystems/Authentication/kerberos/kerberos-authentication-context.xml +++ b/config/alfresco/subsystems/Authentication/kerberos/kerberos-authentication-context.xml @@ -87,6 +87,9 @@ ${kerberos.authentication.cifs.configEntryName} + + true + \ No newline at end of file diff --git a/source/java/org/alfresco/filesys/auth/cifs/AlfrescoCifsAuthenticator.java b/source/java/org/alfresco/filesys/auth/cifs/AlfrescoCifsAuthenticator.java index 3bf73c25cb..72e4baf044 100644 --- a/source/java/org/alfresco/filesys/auth/cifs/AlfrescoCifsAuthenticator.java +++ b/source/java/org/alfresco/filesys/auth/cifs/AlfrescoCifsAuthenticator.java @@ -26,9 +26,6 @@ package org.alfresco.filesys.auth.cifs; import java.security.NoSuchAlgorithmException; -import javax.transaction.Status; -import javax.transaction.UserTransaction; - import net.sf.acegisecurity.Authentication; import org.alfresco.filesys.alfresco.AlfrescoClientInfo; @@ -42,6 +39,7 @@ import org.alfresco.jlan.smb.server.SMBSrvSession; import org.alfresco.jlan.util.HexDump; import org.alfresco.repo.security.authentication.NTLMMode; import org.alfresco.repo.security.authentication.ntlm.NTLMPassthruToken; +import org.alfresco.repo.transaction.RetryingTransactionHelper; /** * Alfresco Authenticator Class @@ -94,7 +92,7 @@ public class AlfrescoCifsAuthenticator extends CifsAuthenticatorBase * @param sess Server session * @param alg Encryption algorithm */ - public int authenticateUser(ClientInfo client, SrvSession sess, int alg) + public int authenticateUser(final ClientInfo client, final SrvSession sess, final int alg) { // Check that the client is an Alfresco client @@ -138,7 +136,6 @@ public class AlfrescoCifsAuthenticator extends CifsAuthenticatorBase // Check if this is a guest logon int authSts = AUTH_DISALLOW; - UserTransaction tx = null; try { @@ -172,24 +169,30 @@ public class AlfrescoCifsAuthenticator extends CifsAuthenticatorBase else if ( getNTLMAuthenticator().getNTLMMode() == NTLMMode.MD4_PROVIDER) { // Start a transaction + authSts = doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + + public Integer execute() throws Throwable + { + // Perform local MD4 password check + return doMD4UserAuthentication(client, sess, alg); + } + }); - tx = createTransaction(); - tx.begin(); - - // Perform local MD4 password check - - authSts = doMD4UserAuthentication(client, sess, alg); } else { // Start a transaction - - tx = createTransaction(); - tx.begin(); + authSts = doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + + public Integer execute() throws Throwable + { + // Perform passthru authentication password check + return doPassthruUserAuthentication(client, sess, alg); + } + }); - // Perform passthru authentication password check - - authSts = doPassthruUserAuthentication(client, sess, alg); } // Check if the logon status indicates a guest logon @@ -217,34 +220,6 @@ public class AlfrescoCifsAuthenticator extends CifsAuthenticatorBase if ( logger.isDebugEnabled()) logger.debug( ex); } - finally - { - // Commit the transaction - - if ( tx != null) - { - try - { - // Commit or rollback the transaction - - if ( tx.getStatus() == Status.STATUS_MARKED_ROLLBACK) - { - // Transaction is marked for rollback - - tx.rollback(); - } - else - { - // Commit the transaction - - tx.commit(); - } - } - catch ( Exception ex) - { - } - } - } // Check for an administrator logon diff --git a/source/java/org/alfresco/filesys/auth/cifs/CifsAuthenticatorBase.java b/source/java/org/alfresco/filesys/auth/cifs/CifsAuthenticatorBase.java index 3bb68dd05a..f53df4d83a 100644 --- a/source/java/org/alfresco/filesys/auth/cifs/CifsAuthenticatorBase.java +++ b/source/java/org/alfresco/filesys/auth/cifs/CifsAuthenticatorBase.java @@ -24,8 +24,6 @@ */ package org.alfresco.filesys.auth.cifs; -import javax.transaction.UserTransaction; - import net.sf.acegisecurity.Authentication; import org.alfresco.config.ConfigElement; @@ -48,6 +46,7 @@ import org.alfresco.repo.security.authentication.AuthenticationComponent; import org.alfresco.repo.security.authentication.MD4PasswordEncoder; import org.alfresco.repo.security.authentication.MD4PasswordEncoderImpl; import org.alfresco.repo.security.authentication.ntlm.NLTMAuthenticator; +import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.AuthenticationService; @@ -348,49 +347,28 @@ public abstract class CifsAuthenticatorBase extends CifsAuthenticator implements * @param client * ClientInfo */ - protected final void getHomeFolderForUser(ClientInfo client) + protected final void getHomeFolderForUser(final ClientInfo client) { // Check if the client is an Alfresco client, and not a null logon - - if ( client instanceof AlfrescoClientInfo == false || - client.isNullSession() == true) - return; - - AlfrescoClientInfo alfClient = (AlfrescoClientInfo) client; - + + if (client instanceof AlfrescoClientInfo == false || client.isNullSession() == true) + return; + + final AlfrescoClientInfo alfClient = (AlfrescoClientInfo) client; + // Get the home folder for the user - - UserTransaction tx = getTransactionService().getUserTransaction(); - NodeRef homeSpaceRef = null; - - try + + doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() { - tx.begin(); - homeSpaceRef = (NodeRef) getNodeService().getProperty(getPersonService().getPerson(client.getUserName()), ContentModel.PROP_HOMEFOLDER); - alfClient.setHomeFolder( homeSpaceRef); - tx.commit(); - } - catch (Throwable ex) - { - try + + public Object execute() throws Throwable { - tx.rollback(); + NodeRef homeSpaceRef = (NodeRef) getNodeService().getProperty( + getPersonService().getPerson(client.getUserName()), ContentModel.PROP_HOMEFOLDER); + alfClient.setHomeFolder(homeSpaceRef); + return null; } - catch (Throwable ex2) - { - logger.error("Failed to rollback transaction", ex2); - } - - // Re-throw the exception - if (ex instanceof RuntimeException) - { - throw (RuntimeException) ex; - } - else - { - throw new RuntimeException("Error during execution of transaction.", ex); - } - } + }); } /** @@ -400,58 +378,29 @@ public abstract class CifsAuthenticatorBase extends CifsAuthenticator implements * String * @return String */ - protected final String mapUserNameToPerson(String userName) + protected final String mapUserNameToPerson(final String userName) { - // Get the home folder for the user - - UserTransaction tx = getTransactionService().getUserTransaction(); - String personName = null; - - try + return doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() { - tx.begin(); - personName = getPersonService().getUserIdentifier( userName); - tx.commit(); - // Check if the person exists - - if (personName == null) { - - tx = getTransactionService().getNonPropagatingUserTransaction( false); - tx.begin(); - - getPersonService().getPerson( userName); - personName = getPersonService().getUserIdentifier( userName); - - tx.commit(); - } - } - catch (Throwable ex) - { - try + public String execute() throws Throwable { - tx.rollback(); + // Get the home folder for the user + + String personName = getPersonService().getUserIdentifier(userName); + + // Check if the person exists + + if (personName == null) + { + // Force creation of a person if possible + getPersonService().getPerson(userName); + personName = getPersonService().getUserIdentifier(userName); + return personName == null ? userName : personName; + } + return personName; } - catch (Throwable ex2) - { - logger.error("Failed to rollback transaction", ex2); - } - - // Re-throw the exception - - if (ex instanceof RuntimeException) - { - throw (RuntimeException) ex; - } - else - { - throw new RuntimeException("Error during execution of transaction.", ex); - } - } - - // Return the person name - - return personName; + }); } /** @@ -545,7 +494,7 @@ public abstract class CifsAuthenticatorBase extends CifsAuthenticator implements * * @return TransactionService */ - protected final TransactionService getTransactionService() + private final TransactionService getTransactionService() { return this.transactionService; } @@ -565,62 +514,48 @@ public abstract class CifsAuthenticatorBase extends CifsAuthenticator implements * @param cInfo * ClientInfo */ - protected final void checkForAdminUserName(ClientInfo cInfo) { - + protected final void checkForAdminUserName(final ClientInfo cInfo) + { + // Check if the user name is an administrator - UserTransaction tx = createTransaction(); + doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { - try { - tx.begin(); + public Object execute() throws Throwable + { + if (cInfo.getLogonType() == ClientInfo.LogonNormal + && getAuthorityService().isAdminAuthority(cInfo.getUserName())) + { - if ( cInfo.getLogonType() == ClientInfo.LogonNormal && getAuthorityService().isAdminAuthority(cInfo.getUserName())) { - - // Indicate that this is an administrator logon + // Indicate that this is an administrator logon - cInfo.setLogonType(ClientInfo.LogonAdmin); + cInfo.setLogonType(ClientInfo.LogonAdmin); + } + return null; } - tx.commit(); - } - catch (Throwable ex) { - try { - tx.rollback(); - } - catch (Throwable ex2) { - logger.error("Failed to rollback transaction", ex2); - } - - // Re-throw the exception - - if ( ex instanceof RuntimeException) { - throw (RuntimeException) ex; - } - else { - throw new RuntimeException("Error during execution of transaction.", ex); - } - } + }); } /** - * Create a transaction, this will be a wrteable transaction unless the system is in read-only mode. return - * UserTransaction + * Does work in a transaction. This will be a writeable transaction unless the system is in read-only mode. * - * @return the user transaction + * @param callback + * a callback that does the work + * @return the result, or null if not applicable */ - protected final UserTransaction createTransaction() + protected T doInTransaction(RetryingTransactionHelper.RetryingTransactionCallback callback) { // Get the transaction service - + TransactionService txService = getTransactionService(); - + // DEBUG - - if ( logger.isDebugEnabled()) + + if (logger.isDebugEnabled()) logger.debug("Using " + (txService.isReadOnly() ? "ReadOnly" : "Write") + " transaction"); - - // Create the transaction - - return txService.getUserTransaction( txService.isReadOnly() ? true : false); + + return txService.getRetryingTransactionHelper().doInTransaction(callback, txService.isReadOnly()); } /** diff --git a/source/java/org/alfresco/filesys/auth/cifs/EnterpriseCifsAuthenticator.java b/source/java/org/alfresco/filesys/auth/cifs/EnterpriseCifsAuthenticator.java index a1e39796c0..60ea1bc532 100644 --- a/source/java/org/alfresco/filesys/auth/cifs/EnterpriseCifsAuthenticator.java +++ b/source/java/org/alfresco/filesys/auth/cifs/EnterpriseCifsAuthenticator.java @@ -41,8 +41,6 @@ import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; import javax.security.sasl.RealmCallback; -import javax.transaction.Status; -import javax.transaction.UserTransaction; import org.alfresco.config.ConfigElement; import org.alfresco.error.AlfrescoRuntimeException; @@ -80,6 +78,7 @@ import org.alfresco.jlan.util.DataPacker; import org.alfresco.jlan.util.HexDump; import org.alfresco.repo.security.authentication.NTLMMode; import org.alfresco.repo.security.authentication.ntlm.NLTMAuthenticator; +import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.ietf.jgss.Oid; /** @@ -634,7 +633,7 @@ public class EnterpriseCifsAuthenticator extends CifsAuthenticatorBase implement * @param reqPkt SMBSrvPacket * @exception SMBSrvException */ - public void processSessionSetup(SMBSrvSession sess, SMBSrvPacket reqPkt) + public void processSessionSetup(final SMBSrvSession sess, final SMBSrvPacket reqPkt) throws SMBSrvException { // Check that the received packet looks like a valid NT session setup andX request @@ -646,18 +645,21 @@ public class EnterpriseCifsAuthenticator extends CifsAuthenticatorBase implement if ( reqPkt.getParameterCount() == 13) { - UserTransaction tx = null; - try { // Start a transaction - - tx = createTransaction(); - tx.begin(); - // Process the hashed password session setup - - doHashedPasswordLogon( sess, reqPkt); + doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + + public Object execute() throws Throwable + { + // Process the hashed password session setup + + doHashedPasswordLogon(sess, reqPkt); + return null; + } + }); } catch ( Exception ex) { @@ -665,34 +667,6 @@ public class EnterpriseCifsAuthenticator extends CifsAuthenticatorBase implement throw new SMBSrvException( SMBStatus.NTAccessDenied, SMBStatus.ErrDos, SMBStatus.DOSAccessDenied); } - finally - { - // Commit the transaction - - if ( tx != null) - { - try - { - // Commit or rollback the transaction - - if ( tx.getStatus() == Status.STATUS_MARKED_ROLLBACK) - { - // Transaction is marked for rollback - - tx.rollback(); - } - else - { - // Commit the transaction - - tx.commit(); - } - } - catch ( Exception ex) - { - } - } - } // Hashed password processing complete @@ -704,21 +678,21 @@ public class EnterpriseCifsAuthenticator extends CifsAuthenticatorBase implement int maxBufSize = reqPkt.getParameter(2); int maxMpx = reqPkt.getParameter(3); int vcNum = reqPkt.getParameter(4); - int secBlobLen = reqPkt.getParameter(7); + final int secBlobLen = reqPkt.getParameter(7); int capabs = reqPkt.getParameterLong(10); // Extract the client details from the session setup request int dataPos = reqPkt.getByteOffset(); - byte[] buf = reqPkt.getBuffer(); + final byte[] buf = reqPkt.getBuffer(); // Determine if ASCII or unicode strings are being used - boolean isUni = reqPkt.isUnicode(); + final boolean isUni = reqPkt.isUnicode(); // Make a note of the security blob position - int secBlobPos = dataPos; + final int secBlobPos = dataPos; // Extract the clients primary domain name string @@ -764,7 +738,7 @@ public class EnterpriseCifsAuthenticator extends CifsAuthenticatorBase implement // Create the client information and store in the session - ClientInfo client = new AlfrescoClientInfo(); + final ClientInfo client = new AlfrescoClientInfo(); client.setDomain(domain); client.setOperatingSystem(clientOS); @@ -786,13 +760,11 @@ public class EnterpriseCifsAuthenticator extends CifsAuthenticatorBase implement // Process the security blob byte[] respBlob = null; - boolean isNTLMSSP = false; - - UserTransaction tx = null; + final boolean isNTLMSSP; try { - + // Check if the blob has the NTLMSSP signature if ( secBlobLen >= NTLM.Signature.length) { @@ -803,39 +775,36 @@ public class EnterpriseCifsAuthenticator extends CifsAuthenticatorBase implement while ( idx < NTLM.Signature.length && buf[secBlobPos + idx] == NTLM.Signature[ idx]) idx++; - if ( idx == NTLM.Signature.length) - isNTLMSSP = true; + isNTLMSSP = ( idx == NTLM.Signature.length); } - + else { + isNTLMSSP = false; + } + // Start a transaction - tx = createTransaction(); - tx.begin(); - - // Process the security blob - - if ( isNTLMSSP == true) + respBlob = doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() { - // Process an NTLMSSP security blob - - respBlob = doNtlmsspSessionSetup( sess, client, buf, secBlobPos, secBlobLen, isUni); - } - else - { - // Process an SPNEGO security blob - - respBlob = doSpnegoSessionSetup( sess, client, buf, secBlobPos, secBlobLen, isUni); - } - } - catch (SMBSrvException ex) - { - // Cleanup any stored context + + public byte[] execute() throws Throwable + { + // Process the security blob + + if (isNTLMSSP) + { + // Process an NTLMSSP security blob + + return doNtlmsspSessionSetup(sess, client, buf, secBlobPos, secBlobLen, isUni); + } + else + { + // Process an SPNEGO security blob + + return doSpnegoSessionSetup(sess, client, buf, secBlobPos, secBlobLen, isUni); + } + } + }); - sess.removeSetupObject( client.getProcessId()); - - // Rethrow the exception - - throw ex; } catch ( Exception ex) { @@ -847,34 +816,6 @@ public class EnterpriseCifsAuthenticator extends CifsAuthenticatorBase implement throw new SMBSrvException( SMBStatus.NTAccessDenied, SMBStatus.ErrDos, SMBStatus.DOSAccessDenied); } - finally - { - // Commit the transaction - - if ( tx != null) - { - try - { - // Commit or rollback the transaction - - if ( tx.getStatus() == Status.STATUS_MARKED_ROLLBACK) - { - // Transaction is marked for rollback - - tx.rollback(); - } - else - { - // Commit the transaction - - tx.commit(); - } - } - catch ( Exception ex) - { - } - } - } // Debug @@ -1046,11 +987,11 @@ public class EnterpriseCifsAuthenticator extends CifsAuthenticatorBase implement // Pack the security blob int pos = respPkt.getByteOffset(); - buf = respPkt.getBuffer(); + byte[] buf1 = respPkt.getBuffer(); if ( respBlob != null) { - System.arraycopy( respBlob, 0, buf, pos, respBlob.length); + System.arraycopy( respBlob, 0, buf1, pos, respBlob.length); pos += respBlob.length; } @@ -1059,9 +1000,9 @@ public class EnterpriseCifsAuthenticator extends CifsAuthenticatorBase implement if ( isUni) pos = DataPacker.wordAlign(pos); - pos = DataPacker.putString("Java", buf, pos, true, isUni); - pos = DataPacker.putString("Alfresco CIFS Server " + sess.getServer().isVersion(), buf, pos, true, isUni); - pos = DataPacker.putString(getCIFSConfig().getDomainName(), buf, pos, true, isUni); + pos = DataPacker.putString("Java", buf1, pos, true, isUni); + pos = DataPacker.putString("Alfresco CIFS Server " + sess.getServer().isVersion(), buf1, pos, true, isUni); + pos = DataPacker.putString(getCIFSConfig().getDomainName(), buf1, pos, true, isUni); respPkt.setByteCount(pos - respPkt.getByteOffset()); } diff --git a/source/java/org/alfresco/filesys/auth/cifs/PassthruCifsAuthenticator.java b/source/java/org/alfresco/filesys/auth/cifs/PassthruCifsAuthenticator.java index 77d7fa641c..32c7e6a7d7 100644 --- a/source/java/org/alfresco/filesys/auth/cifs/PassthruCifsAuthenticator.java +++ b/source/java/org/alfresco/filesys/auth/cifs/PassthruCifsAuthenticator.java @@ -28,9 +28,6 @@ import java.util.ArrayList; import java.util.Hashtable; import java.util.List; -import javax.transaction.Status; -import javax.transaction.UserTransaction; - import org.alfresco.config.ConfigElement; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.filesys.alfresco.AlfrescoClientInfo; @@ -68,6 +65,7 @@ import org.alfresco.model.ContentModel; import org.alfresco.repo.security.authentication.AuthenticationComponent; import org.alfresco.repo.security.authentication.NTLMMode; import org.alfresco.repo.security.authentication.ntlm.NLTMAuthenticator; +import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.service.cmr.repository.NodeRef; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -158,14 +156,14 @@ public class PassthruCifsAuthenticator extends CifsAuthenticatorBase implements * @param alg int * @return int */ - public int authenticateUser(ClientInfo client, SrvSession sess, int alg) + public int authenticateUser(final ClientInfo client, final SrvSession sess, int alg) { // Check that the client is an Alfresco client if ( client instanceof AlfrescoClientInfo == false) return ICifsAuthenticator.AUTH_DISALLOW; - AlfrescoClientInfo alfClient = (AlfrescoClientInfo) client; + final AlfrescoClientInfo alfClient = (AlfrescoClientInfo) client; // The null session will only be allowed to connect to the IPC$ named pipe share. @@ -181,224 +179,196 @@ public class PassthruCifsAuthenticator extends CifsAuthenticatorBase implements // Start a transaction - UserTransaction tx = createTransaction(); - int authSts = AUTH_DISALLOW; - - try - { - // Start the transaction - - tx.begin(); - - // Check if the client is already authenticated, and it is not a null logon - - if ( alfClient.getAuthenticationToken() != null && client.getLogonType() != ClientInfo.LogonNull) + return doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback(){ + + public Integer execute() throws Throwable { - // Use the existing authentication token + int authSts = AUTH_DISALLOW; - getAuthenticationComponent().setCurrentUser( mapUserNameToPerson( client.getUserName())); - - // Debug - - if ( logger.isDebugEnabled()) - logger.debug("Re-using existing authentication token"); - - // Return the authentication status - - return client.getLogonType() != ClientInfo.LogonGuest ? AUTH_ALLOW : AUTH_GUEST; - } - - // Check if this is a guest logon - - if ( client.isGuest() || client.getUserName().equalsIgnoreCase(getGuestUserName())) - { - // Check if guest logons are allowed - - if ( allowGuest() == false) - return AUTH_DISALLOW; - - // Get a guest authentication token - - doGuestLogon( client, sess); - - // Indicate logged on as guest - - authSts = AUTH_GUEST; - - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug("Authenticated user " + client.getUserName() + " sts=" + getStatusAsString(authSts)); - - // Return the guest status - - return authSts; - } - - // Find the active authentication session details for the server session - - PassthruDetails passDetails = m_sessions.get(sess.getUniqueId()); - - if (passDetails != null) - { - try { - - // Authenticate the user by passing the hashed password to the authentication server - // using the session that has already been setup. - - AuthenticateSession authSess = passDetails.getAuthenticateSession(); - authSess.doSessionSetup(client.getDomain(), client.getUserName(), null, client.getANSIPassword(), client.getPassword(), 0); - - // Check if the user has been logged on as a guest - - if (authSess.isGuest()) - { - - // Check if the local server allows guest access - - if (allowGuest() == true) - { - // Get a guest authentication token - - doGuestLogon( client, sess); - - // Allow the user access as a guest - - authSts = ICifsAuthenticator.AUTH_GUEST; - - // Debug - - if (logger.isDebugEnabled()) - logger.debug("Passthru authenticate user=" + client.getUserName() + ", GUEST"); - } - } - else - { - // Map the passthru username to an Alfresco person - - String username = client.getUserName(); - String personName = getPersonService().getUserIdentifier( username); - - if ( personName != null) - { - // Use the person name as the current user - - alfClient.setAuthenticationToken( getAuthenticationComponent().setCurrentUser(personName)); - - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug("Setting current user using person " + personName + " (username " + username + ")"); - - // Allow the user full access to the server - - authSts = ICifsAuthenticator.AUTH_ALLOW; - - // Debug - - if (logger.isDebugEnabled()) - logger.debug("Passthru authenticate user=" + client.getUserName() + ", FULL"); - } - else if ( logger.isDebugEnabled()) - logger.debug("Failed to find person matching user " + username); - } - } - catch (Exception ex) - { - - // Debug - - logger.error(ex); - } - - // Keep the authentication session if the user session is an SMB session, else close the - // session now - - if ((sess instanceof SMBSrvSession) == false) - { - - // Remove the passthru session from the active list - - m_sessions.remove(sess.getUniqueId()); - - // Close the passthru authentication session - - try - { - - // Close the authentication session - - AuthenticateSession authSess = passDetails.getAuthenticateSession(); - authSess.CloseSession(); - - // DEBUG - - if (logger.isDebugEnabled()) - logger.debug("Closed auth session, sessId=" + authSess.getSessionId()); - } - catch (Exception ex) - { - - // Debug - - logger.error("Passthru error closing session (auth user)", ex); - } - } - } - else - { - - // DEBUG - - if (logger.isDebugEnabled()) - logger.debug(" No PassthruDetails for " + sess.getUniqueId()); - } - } - catch ( Exception ex) - { - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug( ex); - - // Return an access denied status - - return AUTH_DISALLOW; - } - finally - { - // Commit the transaction - - if ( tx != null) - { - try - { - // Commit or rollback the transaction + // Check if the client is already authenticated, and it is not a null logon - if ( tx.getStatus() == Status.STATUS_MARKED_ROLLBACK) + if ( alfClient.getAuthenticationToken() != null && client.getLogonType() != ClientInfo.LogonNull) { - // Transaction is marked for rollback + // Use the existing authentication token - tx.rollback(); + getAuthenticationComponent().setCurrentUser( mapUserNameToPerson( client.getUserName())); + + // Debug + + if ( logger.isDebugEnabled()) + logger.debug("Re-using existing authentication token"); + + // Return the authentication status + + return client.getLogonType() != ClientInfo.LogonGuest ? AUTH_ALLOW : AUTH_GUEST; + } + + // Check if this is a guest logon + + if ( client.isGuest() || client.getUserName().equalsIgnoreCase(getGuestUserName())) + { + // Check if guest logons are allowed + + if ( allowGuest() == false) + return AUTH_DISALLOW; + + // Get a guest authentication token + + doGuestLogon( client, sess); + + // Indicate logged on as guest + + authSts = AUTH_GUEST; + + // DEBUG + + if ( logger.isDebugEnabled()) + logger.debug("Authenticated user " + client.getUserName() + " sts=" + getStatusAsString(authSts)); + + // Return the guest status + + return authSts; + } + + // Find the active authentication session details for the server session + + PassthruDetails passDetails = m_sessions.get(sess.getUniqueId()); + + if (passDetails != null) + { + + try + { + + // Authenticate the user by passing the hashed password to the authentication server + // using the session that has already been setup. + + AuthenticateSession authSess = passDetails.getAuthenticateSession(); + authSess.doSessionSetup(client.getDomain(), client.getUserName(), null, client.getANSIPassword(), client.getPassword(), 0); + + // Check if the user has been logged on as a guest + + if (authSess.isGuest()) + { + + // Check if the local server allows guest access + + if (allowGuest() == true) + { + // Get a guest authentication token + + doGuestLogon( client, sess); + + // Allow the user access as a guest + + authSts = ICifsAuthenticator.AUTH_GUEST; + + // Debug + + if (logger.isDebugEnabled()) + logger.debug("Passthru authenticate user=" + client.getUserName() + ", GUEST"); + } + } + else + { + // Map the passthru username to an Alfresco person + + String username = client.getUserName(); + String personName = getPersonService().getUserIdentifier( username); + + if ( personName != null) + { + // Use the person name as the current user + + alfClient.setAuthenticationToken( getAuthenticationComponent().setCurrentUser(personName)); + + // DEBUG + + if ( logger.isDebugEnabled()) + logger.debug("Setting current user using person " + personName + " (username " + username + ")"); + + // Allow the user full access to the server + + authSts = ICifsAuthenticator.AUTH_ALLOW; + + // Debug + + if (logger.isDebugEnabled()) + logger.debug("Passthru authenticate user=" + client.getUserName() + ", FULL"); + } + else if ( logger.isDebugEnabled()) + logger.debug("Failed to find person matching user " + username); + } + } + catch (Exception ex) + { + + // Debug + + logger.error(ex); + } + + // Keep the authentication session if the user session is an SMB session, else close the + // session now + + if ((sess instanceof SMBSrvSession) == false) + { + + // Remove the passthru session from the active list + + m_sessions.remove(sess.getUniqueId()); + + // Close the passthru authentication session + + try + { + + // Close the authentication session + + AuthenticateSession authSess = passDetails.getAuthenticateSession(); + authSess.CloseSession(); + + // DEBUG + + if (logger.isDebugEnabled()) + logger.debug("Closed auth session, sessId=" + authSess.getSessionId()); + } + catch (Exception ex) + { + + // Debug + + logger.error("Passthru error closing session (auth user)", ex); + } + } } else { - // Commit the transaction - - tx.commit(); + + // DEBUG + + if (logger.isDebugEnabled()) + logger.debug(" No PassthruDetails for " + sess.getUniqueId()); } } catch ( Exception ex) { + // DEBUG + + if ( logger.isDebugEnabled()) + logger.debug( ex); + + // Return an access denied status + + return AUTH_DISALLOW; } - } - } - - // Return the authentication status + + // Return the authentication status - return authSts; + return authSts; + }}); } /** @@ -954,7 +924,7 @@ public class PassthruCifsAuthenticator extends CifsAuthenticatorBase implements * @param type3Msg Type3NTLMMessage * @exception SMBSrvException */ - private final void doNTLMv1Logon(SMBSrvSession sess, ClientInfo client, Type3NTLMMessage type3Msg) + private final void doNTLMv1Logon(SMBSrvSession sess, final ClientInfo client, Type3NTLMMessage type3Msg) throws SMBSrvException { // Get the type 2 message that contains the challenge sent to the client @@ -963,7 +933,7 @@ public class PassthruCifsAuthenticator extends CifsAuthenticatorBase implements // Get the NTLM logon details - String userName = type3Msg.getUserName(); + final String userName = type3Msg.getUserName(); // Check for a null logon @@ -1016,70 +986,59 @@ public class PassthruCifsAuthenticator extends CifsAuthenticatorBase implements { // Wrap the service calls in a transaction - UserTransaction tx = createTransaction(); - - try + doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() { - // Start the transaction - - tx.begin(); - // Map the passthru username to an Alfresco person - - NodeRef userNode = getPersonService().getPerson(userName); - if ( userNode != null) + public Object execute() throws Throwable { - // Get the person name and use that as the current user to line up with permission checks - - String personName = (String) getNodeService().getProperty(userNode, ContentModel.PROP_USERNAME); - getAuthenticationComponent().setCurrentUser(personName); - - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug("Setting current user using person " + personName + " (username " + userName + ")"); - } - else - { - // Set using the user name - - getAuthenticationComponent().setCurrentUser( userName); + // Map the passthru username to an Alfresco person - // DEBUG - - if ( logger.isDebugEnabled()) - logger.debug("Setting current user using username " + userName); - } - - // Get the authentication token and store - - AlfrescoClientInfo alfClient = (AlfrescoClientInfo) client; - alfClient.setAuthenticationToken( getAuthenticationComponent().getCurrentAuthentication()); - - // Indicate that the client is logged on - - client.setLogonType( ClientInfo.LogonNormal); - - // Debug - - if (logger.isDebugEnabled()) - logger.debug("Passthru authenticate user=" + userName + ", FULL"); - } - finally - { - // Commit the transaction - - if ( tx != null) - { - try { - tx.commit(); - } - catch (Exception ex) + NodeRef userNode = getPersonService().getPerson(userName); + if (userNode != null) { - // Sink it + // Get the person name and use that as the current user to line up with permission + // checks + + String personName = (String) getNodeService().getProperty(userNode, + ContentModel.PROP_USERNAME); + getAuthenticationComponent().setCurrentUser(personName); + + // DEBUG + + if (logger.isDebugEnabled()) + logger.debug("Setting current user using person " + personName + " (username " + + userName + ")"); } + else + { + // Set using the user name + + getAuthenticationComponent().setCurrentUser(userName); + + // DEBUG + + if (logger.isDebugEnabled()) + logger.debug("Setting current user using username " + userName); + } + + // Get the authentication token and store + + AlfrescoClientInfo alfClient = (AlfrescoClientInfo) client; + alfClient.setAuthenticationToken(getAuthenticationComponent().getCurrentAuthentication()); + + // Indicate that the client is logged on + + client.setLogonType(ClientInfo.LogonNormal); + + // Debug + + if (logger.isDebugEnabled()) + logger.debug("Passthru authenticate user=" + userName + ", FULL"); + + return null; } - } + }); + } // Update the client details