diff --git a/source/java/org/alfresco/filesys/server/auth/AlfrescoAuthenticator.java b/source/java/org/alfresco/filesys/server/auth/AlfrescoAuthenticator.java index 24c6d92ff5..5dd802c000 100644 --- a/source/java/org/alfresco/filesys/server/auth/AlfrescoAuthenticator.java +++ b/source/java/org/alfresco/filesys/server/auth/AlfrescoAuthenticator.java @@ -17,32 +17,11 @@ package org.alfresco.filesys.server.auth; import java.security.NoSuchAlgorithmException; -import java.util.Random; -import javax.transaction.UserTransaction; - -import net.sf.acegisecurity.Authentication; - -import org.alfresco.config.ConfigElement; import org.alfresco.filesys.server.SrvSession; -import org.alfresco.filesys.server.config.InvalidConfigurationException; -import org.alfresco.filesys.server.config.ServerConfiguration; -import org.alfresco.filesys.server.core.SharedDevice; import org.alfresco.filesys.smb.server.SMBSrvSession; import org.alfresco.filesys.util.DataPacker; -import org.alfresco.model.ContentModel; -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.NTLMMode; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.security.PersonService; -import org.alfresco.service.transaction.TransactionService; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import com.sun.star.uno.RuntimeException; /** * Alfresco Authenticator Class @@ -57,32 +36,6 @@ import com.sun.star.uno.RuntimeException; */ public class AlfrescoAuthenticator extends SrvAuthenticator { - // Logging - - private static final Log logger = LogFactory.getLog("org.alfresco.smb.protocol.auth"); - - // Random number generator used to generate challenge keys - - private Random m_random = new Random(System.currentTimeMillis()); - - // Server configuration - - private ServerConfiguration m_config; - - // Authentication component, used to access internal authentication functions - - private AuthenticationComponent m_authComponent; - - // MD4 hash decoder - - private MD4PasswordEncoder m_md4Encoder = new MD4PasswordEncoderImpl(); - - // Various services required to get user information - - private NodeService m_nodeService; - private PersonService m_personService; - private TransactionService m_transactionService; - /** * Default Constructor * @@ -94,24 +47,6 @@ public class AlfrescoAuthenticator extends SrvAuthenticator setEncryptedPasswords(true); } - /** - * Authenticate the connection to a share - * - * @param client ClienInfo - * @param share SharedDevice - * @param pwd Share level password. - * @param sess Server session - * @return Authentication status. - */ - public int authenticateShareConnect(ClientInfo client, SharedDevice share, String pwd, SrvSession sess) - { - // Allow write access - // - // Main authentication is handled by authenticateUser() - - return SrvAuthenticator.Writeable; - } - /** * Authenticate a user * @@ -160,7 +95,7 @@ public class AlfrescoAuthenticator extends SrvAuthenticator int authSts = AUTH_DISALLOW; - if ( client.isGuest()) + if ( client.isGuest() || client.getUserName().equalsIgnoreCase(GUEST_USERNAME)) { // Check if guest logons are allowed @@ -169,18 +104,20 @@ public class AlfrescoAuthenticator extends SrvAuthenticator // Get a guest authentication token - m_authComponent.setGuestUserAsCurrentUser(); - Authentication authToken = m_authComponent.getCurrentAuthentication(); - - client.setAuthenticationToken( authToken); - - // Set the home folder for the guest user - - getHomeFolderForUser( client); + 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; } // Check if MD4 or passthru mode is configured @@ -191,6 +128,26 @@ public class AlfrescoAuthenticator extends SrvAuthenticator authSts = doMD4UserAuthentication(client, sess, alg); } + + // Check if the logon status indicates a guest logon + + if ( authSts == AUTH_GUEST) + { + // Only allow the guest logon if user mapping is enabled + + if ( mapUnknownUserToGuest()) + { + // Logon as guest, setup the security context + + doGuestLogon( client, sess); + } + else + { + // Do not allow the guest logon + + authSts = AUTH_DISALLOW; + } + } // DEBUG @@ -243,47 +200,6 @@ public class AlfrescoAuthenticator extends SrvAuthenticator return key; } - /** - * Search for the required user account details in the defined user list - * - * @param user String - * @return UserAccount - */ - public UserAccount getUserDetails(String user) - { - return null; - } - - /** - * Initialize the authenticator - * - * @param config ServerConfiguration - * @param params ConfigElement - * @exception InvalidConfigurationException - */ - public void initialize(ServerConfiguration config, ConfigElement params) throws InvalidConfigurationException - { - // Save the server configuration so we can access the authentication component - - m_config = config; - - // Check that the required authentication classes are available - - m_authComponent = m_config.getAuthenticationComponent(); - - if ( m_authComponent == null) - throw new InvalidConfigurationException("Authentication component not available"); - - if ( m_authComponent.getNTLMMode() != NTLMMode.MD4_PROVIDER) - throw new InvalidConfigurationException("Required authentication mode not available"); - - // Get hold of various services - - m_nodeService = config.getNodeService(); - m_personService = config.getPersonService(); - m_transactionService = config.getTransactionService(); - } - /** * Perform MD4 user authentication * @@ -362,46 +278,4 @@ public class AlfrescoAuthenticator extends SrvAuthenticator return allowGuest() ? SrvAuthenticator.AUTH_GUEST : SrvAuthenticator.AUTH_DISALLOW; } - - /** - * Get the home folder for the user - * - * @param client ClientInfo - */ - private final void getHomeFolderForUser(ClientInfo client) - { - // Get the home folder for the user - - UserTransaction tx = m_transactionService.getUserTransaction(); - NodeRef homeSpaceRef = null; - - try - { - tx.begin(); - homeSpaceRef = (NodeRef) m_nodeService.getProperty(m_personService.getPerson(client.getUserName()), - ContentModel.PROP_HOMEFOLDER); - client.setHomeFolder( homeSpaceRef); - tx.commit(); - } - catch (Throwable ex) - { - try - { - tx.rollback(); - } - catch (Exception ex2) - { - logger.error("Failed to rollback transaction", ex2); - } - - if(ex instanceof RuntimeException) - { - throw (RuntimeException)ex; - } - else - { - throw new RuntimeException("Failed to get home folder", ex); - } - } - } } \ No newline at end of file diff --git a/source/java/org/alfresco/filesys/server/auth/SrvAuthenticator.java b/source/java/org/alfresco/filesys/server/auth/SrvAuthenticator.java index bbb209a10e..bcee3d2d56 100644 --- a/source/java/org/alfresco/filesys/server/auth/SrvAuthenticator.java +++ b/source/java/org/alfresco/filesys/server/auth/SrvAuthenticator.java @@ -17,12 +17,34 @@ package org.alfresco.filesys.server.auth; import java.security.NoSuchAlgorithmException; +import java.util.Random; + +import javax.transaction.UserTransaction; + +import net.sf.acegisecurity.Authentication; import org.alfresco.config.ConfigElement; import org.alfresco.filesys.server.SrvSession; import org.alfresco.filesys.server.config.InvalidConfigurationException; import org.alfresco.filesys.server.config.ServerConfiguration; import org.alfresco.filesys.server.core.SharedDevice; +import org.alfresco.filesys.server.filesys.DiskDeviceContext; +import org.alfresco.filesys.server.filesys.DiskInterface; +import org.alfresco.filesys.server.filesys.DiskSharedDevice; +import org.alfresco.filesys.server.filesys.SrvDiskInfo; +import org.alfresco.filesys.smb.server.repo.ContentContext; +import org.alfresco.model.ContentModel; +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.NTLMMode; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.AuthenticationService; +import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.service.transaction.TransactionService; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; /** *
@@ -31,6 +53,9 @@ import org.alfresco.filesys.server.core.SharedDevice;
*/
public abstract class SrvAuthenticator
{
+ // Logging
+
+ protected static final Log logger = LogFactory.getLog("org.alfresco.smb.protocol.auth");
// Encryption algorithm types
@@ -61,6 +86,10 @@ public abstract class SrvAuthenticator
public static final int STANDARD_PASSWORD_LEN = 24;
+ // Default guest user name
+
+ protected static final String GUEST_USERNAME = "guest";
+
// Server access mode
private int m_accessMode = SHARE_MODE;
@@ -73,10 +102,38 @@ public abstract class SrvAuthenticator
private PasswordEncryptor m_encryptor = new PasswordEncryptor();
- // Flag to enable/disable the guest account
+ // Flag to enable/disable the guest account, and control mapping of unknown users to the guest account
private boolean m_allowGuest;
+ private boolean m_mapToGuest;
+ // Default guest user name
+
+ private String m_guestUserName = GUEST_USERNAME;
+
+ // Random number generator used to generate challenge keys
+
+ protected Random m_random = new Random(System.currentTimeMillis());
+
+ // Server configuration
+
+ protected ServerConfiguration m_config;
+
+ // Authentication component, used to access internal authentication functions
+
+ protected AuthenticationComponent m_authComponent;
+
+ // MD4 hash decoder
+
+ protected MD4PasswordEncoder m_md4Encoder = new MD4PasswordEncoderImpl();
+
+ // Various services required to get user information
+
+ protected NodeService m_nodeService;
+ protected PersonService m_personService;
+ protected TransactionService m_transactionService;
+ protected AuthenticationService m_authenticationService;
+
/**
* Authenticate a connection to a share.
*
@@ -87,7 +144,14 @@ public abstract class SrvAuthenticator
* @return int Granted file permission level or disallow status if negative. See the
* FilePermission class.
*/
- public abstract int authenticateShareConnect(ClientInfo client, SharedDevice share, String sharePwd, SrvSession sess);
+ public int authenticateShareConnect(ClientInfo client, SharedDevice share, String sharePwd, SrvSession sess)
+ {
+ // Allow write access
+ //
+ // Main authentication is handled by authenticateUser()
+
+ return SrvAuthenticator.Writeable;
+ }
/**
* Authenticate a user. A user may be granted full access, guest access or no access.
@@ -105,7 +169,10 @@ public abstract class SrvAuthenticator
* @param user String
* @return UserAccount
*/
- public abstract UserAccount getUserDetails(String user);
+ public UserAccount getUserDetails(String user)
+ {
+ return null;
+ }
/**
* Authenticate a user using a plain text password.
@@ -150,6 +217,31 @@ public abstract class SrvAuthenticator
*/
public void initialize(ServerConfiguration config, ConfigElement params) throws InvalidConfigurationException
{
+ // Save the server configuration so we can access the authentication component
+
+ m_config = config;
+
+ // Check that the required authentication classes are available
+
+ m_authComponent = m_config.getAuthenticationComponent();
+
+ if ( m_authComponent == null)
+ throw new InvalidConfigurationException("Authentication component not available");
+
+ if ( m_authComponent.getNTLMMode() != NTLMMode.MD4_PROVIDER &&
+ m_authComponent.getNTLMMode() != NTLMMode.PASS_THROUGH)
+ throw new InvalidConfigurationException("Required authentication mode not available");
+
+ // Get hold of various services
+
+ m_nodeService = config.getNodeService();
+ m_personService = config.getPersonService();
+ m_transactionService = config.getTransactionService();
+ m_authenticationService = config.getAuthenticationService();
+
+ // Set the guest user name
+
+ setGuestUserName( m_authComponent.getGuestUserName());
}
/**
@@ -222,6 +314,26 @@ public abstract class SrvAuthenticator
return m_allowGuest;
}
+ /**
+ * Return the guest user name
+ *
+ * @return String
+ */
+ public final String getGuestUserName()
+ {
+ return m_guestUserName;
+ }
+
+ /**
+ * Determine if unknown users should be mapped to the guest account
+ *
+ * @return boolean
+ */
+ public final boolean mapUnknownUserToGuest()
+ {
+ return m_mapToGuest;
+ }
+
/**
* Set the access mode of the server.
*
@@ -252,6 +364,26 @@ public abstract class SrvAuthenticator
m_allowGuest = ena;
}
+ /**
+ * Set the guest user name
+ *
+ * @param guest String
+ */
+ public final void setGuestUserName( String guest)
+ {
+ m_guestUserName = guest;
+ }
+
+ /**
+ * Enable/disable mapping of unknown users to the guest account
+ *
+ * @param ena Enable mapping of unknown users to the guest if true
+ */
+ public final void setMapToGuest( boolean ena)
+ {
+ m_mapToGuest = ena;
+ }
+
/**
* Close the authenticator, perform any cleanup
*/
@@ -367,4 +499,87 @@ public abstract class SrvAuthenticator
return str;
}
+
+ /**
+ * Logon using the guest user account
+ *
+ * @param client ClientInfo
+ * @param sess SrvSession
+ */
+ protected final void doGuestLogon( ClientInfo client, SrvSession sess)
+ {
+ // Get a guest authentication token
+
+ m_authenticationService.authenticateAsGuest();
+ Authentication authToken = m_authComponent.getCurrentAuthentication();
+
+ client.setAuthenticationToken( authToken);
+
+ // Set the home folder for the guest user
+
+ client.setUserName( getGuestUserName());
+ getHomeFolderForUser( client);
+
+ // Mark the client as being a guest logon
+
+ client.setGuest( true);
+
+ // Create a dynamic share for the guest user
+ // Create the disk driver and context
+
+ DiskInterface diskDrv = m_config.getDiskInterface();
+ DiskDeviceContext diskCtx = new ContentContext("", "", client.getHomeFolder());
+
+ // Default the filesystem to look like an 80Gb sized disk with 90% free space
+
+ diskCtx.setDiskInformation(new SrvDiskInfo(2560, 64, 512, 2304));
+
+ // Create a temporary shared device for the users home directory
+
+ sess.addDynamicShare( new DiskSharedDevice( client.getUserName(), diskDrv, diskCtx, SharedDevice.Temporary));
+ }
+
+ /**
+ * Get the home folder for the user
+ *
+ * @param client ClientInfo
+ */
+ protected final void getHomeFolderForUser(ClientInfo client)
+ {
+ // Get the home folder for the user
+
+ UserTransaction tx = m_transactionService.getUserTransaction();
+ NodeRef homeSpaceRef = null;
+
+ try
+ {
+ tx.begin();
+ homeSpaceRef = (NodeRef) m_nodeService.getProperty(m_personService.getPerson(client.getUserName()),
+ ContentModel.PROP_HOMEFOLDER);
+ client.setHomeFolder( homeSpaceRef);
+ 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);
+ }
+ }
+ }
+
}
\ No newline at end of file
diff --git a/source/java/org/alfresco/filesys/server/config/ServerConfiguration.java b/source/java/org/alfresco/filesys/server/config/ServerConfiguration.java
index 5b1e1d0195..cf5416443c 100644
--- a/source/java/org/alfresco/filesys/server/config/ServerConfiguration.java
+++ b/source/java/org/alfresco/filesys/server/config/ServerConfiguration.java
@@ -1451,13 +1451,15 @@ public class ServerConfiguration
else
throw new AlfrescoRuntimeException("Invalid authenticator type, " + authType);
- // Get the allow guest setting
+ // Get the allow guest and map unknown user to guest settings
boolean allowGuest = authElem.getChild("allowGuest") != null ? true : false;
+ boolean mapGuest = authElem.getChild("mapUnknownUserToGuest") != null ? true : false;
// Initialize and set the authenticator class
setAuthenticator(auth, authElem, allowGuest);
+ auth.setMapToGuest( mapGuest);
}
// Add the users
diff --git a/source/java/org/alfresco/filesys/server/filesys/DefaultShareMapper.java b/source/java/org/alfresco/filesys/server/filesys/DefaultShareMapper.java
index 82a70a24b6..7b5a1d9543 100644
--- a/source/java/org/alfresco/filesys/server/filesys/DefaultShareMapper.java
+++ b/source/java/org/alfresco/filesys/server/filesys/DefaultShareMapper.java
@@ -16,6 +16,8 @@
*/
package org.alfresco.filesys.server.filesys;
+import java.util.Enumeration;
+
import org.alfresco.config.ConfigElement;
import org.alfresco.filesys.server.SrvSession;
import org.alfresco.filesys.server.auth.InvalidUserException;
@@ -99,20 +101,33 @@ public class DefaultShareMapper implements ShareMapper
SharedDevice share = null;
- // Find the required share by name/type. Use a case sensitive search first, if that fails
- // use a case
- // insensitive search.
+ // Search the sessions dynamic share list first
- share = m_config.getShares().findShare(name, typ, false);
-
- if (share == null)
- {
-
- // Try a case insensitive search for the required share
-
- share = m_config.getShares().findShare(name, typ, true);
+ if ( sess.hasDynamicShares()) {
+
+ // Check if the required share exists in the sessions dynamic share list
+
+ share = sess.getDynamicShareList().findShare(name, typ, true);
}
+ // If we did not find a share then search the global share list
+
+ if ( share == null)
+ {
+ // Find the required share by name/type. Use a case sensitive search first, if that fails
+ // use a case insensitive search.
+
+ share = m_config.getShares().findShare(name, typ, false);
+
+ if (share == null)
+ {
+
+ // Try a case insensitive search for the required share
+
+ share = m_config.getShares().findShare(name, typ, true);
+ }
+ }
+
// Check if the share is available
if (share != null && share.getContext() != null && share.getContext().isAvailable() == false)
@@ -130,6 +145,30 @@ public class DefaultShareMapper implements ShareMapper
*/
public void deleteShares(SrvSession sess)
{
+ // Check if the session has any dynamic shares
+
+ if ( sess.hasDynamicShares() == false)
+ return;
+
+ // Delete the dynamic shares
+
+ SharedDeviceList shares = sess.getDynamicShareList();
+ Enumeration