mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Merged enterprise features
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2746 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -0,0 +1,932 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Alfresco Network License. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfrescosoftware.com/legal/
|
||||
*
|
||||
* Please view the license relevant to your network subscription.
|
||||
*
|
||||
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
|
||||
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
|
||||
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
|
||||
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
|
||||
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
|
||||
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
|
||||
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
|
||||
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
|
||||
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
|
||||
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
|
||||
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
|
||||
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.ntlm;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.Provider;
|
||||
import java.security.Security;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.AuthenticationServiceException;
|
||||
import net.sf.acegisecurity.BadCredentialsException;
|
||||
import net.sf.acegisecurity.CredentialsExpiredException;
|
||||
import net.sf.acegisecurity.GrantedAuthority;
|
||||
import net.sf.acegisecurity.GrantedAuthorityImpl;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.filesys.server.auth.PasswordEncryptor;
|
||||
import org.alfresco.filesys.server.auth.passthru.AuthenticateSession;
|
||||
import org.alfresco.filesys.server.auth.passthru.PassthruServers;
|
||||
import org.alfresco.filesys.smb.SMBException;
|
||||
import org.alfresco.filesys.smb.SMBStatus;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.security.authentication.AbstractAuthenticationComponent;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||
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.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* NTLM Authentication Component Class
|
||||
*
|
||||
* <p>Provides authentication using passthru to a Windows server(s)/domain controller(s) using the accounts
|
||||
* defined on the passthru server to validate users.
|
||||
*
|
||||
* @author GKSpencer
|
||||
*/
|
||||
public class NTLMAuthenticationComponentImpl extends AbstractAuthenticationComponent
|
||||
{
|
||||
// Logging
|
||||
|
||||
private static final Log logger = LogFactory.getLog("org.alfresco.passthru.auth");
|
||||
|
||||
// Constants
|
||||
//
|
||||
// Standard authorities
|
||||
|
||||
public static final String NTLMAuthorityGuest = "Guest";
|
||||
public static final String NTLMAuthorityAdministrator = "Administrator";
|
||||
|
||||
// Active session timeout
|
||||
|
||||
private static final long DefaultSessionTimeout = 60000L; // 1 minute
|
||||
private static final long MinimumSessionTimeout = 5000L; // 5 seconds
|
||||
|
||||
// Passthru authentication servers
|
||||
|
||||
private PassthruServers m_passthruServers;
|
||||
|
||||
// Password encryptor for generating password hash for local authentication
|
||||
|
||||
private PasswordEncryptor m_encryptor;
|
||||
|
||||
// Allow guest access
|
||||
|
||||
private boolean m_allowGuest;
|
||||
|
||||
// Table of currently active passthru authentications and the associated authentication session
|
||||
//
|
||||
// If the two authentication stages are not completed within a reasonable time the authentication
|
||||
// session will be closed by the reaper thread.
|
||||
|
||||
private Hashtable<NTLMPassthruToken,AuthenticateSession> m_passthruSessions;
|
||||
|
||||
// Active authentication session timeout, in milliseconds
|
||||
|
||||
private long m_passthruSessTmo = DefaultSessionTimeout;
|
||||
|
||||
// Authentication session reaper thread
|
||||
|
||||
private PassthruReaperThread m_reaperThread;
|
||||
|
||||
// Person service, used to map passthru usernames to Alfresco person names
|
||||
|
||||
private PersonService m_personService;
|
||||
private NodeService m_nodeService;
|
||||
|
||||
/**
|
||||
* Passthru Session Reaper Thread
|
||||
*/
|
||||
class PassthruReaperThread extends Thread
|
||||
{
|
||||
// Thread shutdown request flag
|
||||
|
||||
private boolean m_ishutdown;
|
||||
|
||||
// Reaper wakeup interval, in milliseconds
|
||||
|
||||
private long m_wakeupInterval = m_passthruSessTmo / 2;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
PassthruReaperThread()
|
||||
{
|
||||
setDaemon(true);
|
||||
setName("PassthruReaper");
|
||||
start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the wakeup interval
|
||||
*
|
||||
* @param wakeup long
|
||||
*/
|
||||
public final void setWakeup(long wakeup)
|
||||
{
|
||||
m_wakeupInterval = wakeup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main thread code
|
||||
*/
|
||||
public void run()
|
||||
{
|
||||
// Loop until shutdown
|
||||
|
||||
m_ishutdown = false;
|
||||
|
||||
while ( m_ishutdown == false)
|
||||
{
|
||||
// Sleep for a while
|
||||
|
||||
try
|
||||
{
|
||||
sleep( m_wakeupInterval);
|
||||
}
|
||||
catch ( InterruptedException ex)
|
||||
{
|
||||
}
|
||||
|
||||
// Check if there are any active sessions to check
|
||||
|
||||
if ( m_passthruSessions.size() > 0)
|
||||
{
|
||||
// Enumerate the active sessions
|
||||
|
||||
Enumeration<NTLMPassthruToken> tokenEnum = m_passthruSessions.keys();
|
||||
long timeNow = System.currentTimeMillis();
|
||||
|
||||
while (tokenEnum.hasMoreElements())
|
||||
{
|
||||
// Get the current NTLM token and check if it has expired
|
||||
|
||||
NTLMPassthruToken ntlmToken = tokenEnum.nextElement();
|
||||
|
||||
if ( ntlmToken != null && ntlmToken.getAuthenticationExpireTime() < timeNow)
|
||||
{
|
||||
// Authentication token has expired, close the associated authentication session
|
||||
|
||||
AuthenticateSession authSess = m_passthruSessions.get(ntlmToken);
|
||||
if ( authSess != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Close the authentication session
|
||||
|
||||
authSess.CloseSession();
|
||||
}
|
||||
catch ( Exception ex)
|
||||
{
|
||||
// Debug
|
||||
|
||||
if(logger.isDebugEnabled())
|
||||
logger.debug("Error closing expired authentication session", ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the expired token from the active list
|
||||
|
||||
m_passthruSessions.remove(ntlmToken);
|
||||
|
||||
// Debug
|
||||
|
||||
if(logger.isDebugEnabled())
|
||||
logger.debug("Removed expired NTLM token " + ntlmToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Debug
|
||||
|
||||
if(logger.isDebugEnabled())
|
||||
logger.debug("Passthru reaper thread shutdown");
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown the reaper thread
|
||||
*/
|
||||
public final void shutdownRequest()
|
||||
{
|
||||
m_ishutdown = true;
|
||||
this.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*/
|
||||
public NTLMAuthenticationComponentImpl() {
|
||||
|
||||
// Create the passthru authentication server list
|
||||
|
||||
m_passthruServers = new PassthruServers();
|
||||
|
||||
// Create the password encryptor for local password hashing
|
||||
|
||||
m_encryptor = new PasswordEncryptor();
|
||||
|
||||
// Create the active session list and reaper thread
|
||||
|
||||
m_passthruSessions = new Hashtable<NTLMPassthruToken,AuthenticateSession>();
|
||||
m_reaperThread = new PassthruReaperThread();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if guest logons are allowed
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean allowsGuest()
|
||||
{
|
||||
return m_allowGuest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the domain to authenticate against
|
||||
*
|
||||
* @param domain String
|
||||
*/
|
||||
public void setDomain(String domain) {
|
||||
|
||||
// Check if the passthru server list is already configured
|
||||
|
||||
if ( m_passthruServers.getTotalServerCount() > 0)
|
||||
throw new AlfrescoRuntimeException("Passthru server list already configured");
|
||||
|
||||
// Configure the passthru authentication server list using the domain controllers
|
||||
|
||||
m_passthruServers.setDomain(domain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the server(s) to authenticate against
|
||||
*
|
||||
* @param servers String
|
||||
*/
|
||||
public void setServers(String servers) {
|
||||
|
||||
// Check if the passthru server list is already configured
|
||||
|
||||
if ( m_passthruServers.getTotalServerCount() > 0)
|
||||
throw new AlfrescoRuntimeException("Passthru server list already configured");
|
||||
|
||||
// Configure the passthru authenticaiton list using a list of server names/addresses
|
||||
|
||||
m_passthruServers.setServerList(servers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the local server as the authentication server
|
||||
*
|
||||
* @param useLocal String
|
||||
*/
|
||||
public void setUseLocalServer(String useLocal)
|
||||
{
|
||||
// Check if the local server should be used for authentication
|
||||
|
||||
if ( Boolean.parseBoolean(useLocal) == true)
|
||||
{
|
||||
// Check if the passthru server list is already configured
|
||||
|
||||
if ( m_passthruServers.getTotalServerCount() > 0)
|
||||
throw new AlfrescoRuntimeException("Passthru server list already configured");
|
||||
|
||||
try
|
||||
{
|
||||
// Get the list of local network addresses
|
||||
|
||||
InetAddress[] localAddrs = InetAddress.getAllByName(InetAddress.getLocalHost().getHostName());
|
||||
|
||||
// Build the list of local addresses
|
||||
|
||||
if ( localAddrs != null && localAddrs.length > 0)
|
||||
{
|
||||
StringBuilder addrStr = new StringBuilder();
|
||||
|
||||
for ( InetAddress curAddr : localAddrs)
|
||||
{
|
||||
if ( curAddr.isLoopbackAddress() == false)
|
||||
{
|
||||
addrStr.append(curAddr.getHostAddress());
|
||||
addrStr.append(",");
|
||||
}
|
||||
}
|
||||
|
||||
if ( addrStr.length() > 0)
|
||||
addrStr.setLength(addrStr.length() - 1);
|
||||
|
||||
// Set the server list using the local address list
|
||||
|
||||
m_passthruServers.setServerList(addrStr.toString());
|
||||
}
|
||||
else
|
||||
throw new AlfrescoRuntimeException("No local server address(es)");
|
||||
}
|
||||
catch ( UnknownHostException ex)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Failed to get local address list");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow guest access
|
||||
*
|
||||
* @param guest String
|
||||
*/
|
||||
public void setGuestAccess(String guest)
|
||||
{
|
||||
m_allowGuest = Boolean.parseBoolean(guest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JCE provider
|
||||
*
|
||||
* @param providerClass String
|
||||
*/
|
||||
public void setJCEProvider(String providerClass)
|
||||
{
|
||||
// Set the JCE provider, required to provide various encryption/hashing algorithms not available
|
||||
// in the standard Sun JDK/JRE
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
// Load the JCE provider class and validate
|
||||
|
||||
Object jceObj = Class.forName(providerClass).newInstance();
|
||||
if (jceObj instanceof java.security.Provider)
|
||||
{
|
||||
|
||||
// Inform listeners, validate the configuration change
|
||||
|
||||
Provider jceProvider = (Provider) jceObj;
|
||||
|
||||
// Add the JCE provider
|
||||
|
||||
Security.addProvider(jceProvider);
|
||||
|
||||
// Debug
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Using JCE provider " + providerClass);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AlfrescoRuntimeException("JCE provider class is not a valid Provider class");
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException ex)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("JCE provider class " + providerClass + " not found");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("JCE provider class error", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the authentication session timeout, in seconds
|
||||
*
|
||||
* @param sessTmo String
|
||||
*/
|
||||
public void setSessionTimeout(String sessTmo)
|
||||
{
|
||||
// Convert to an integer value and range check the timeout value
|
||||
|
||||
try
|
||||
{
|
||||
// Convert to an integer value
|
||||
|
||||
long sessTmoMilli = Long.parseLong(sessTmo) * 1000L;
|
||||
|
||||
if ( sessTmoMilli < MinimumSessionTimeout)
|
||||
throw new AlfrescoRuntimeException("Authentication session timeout too low, " + sessTmo);
|
||||
|
||||
// Set the authentication session timeout value
|
||||
|
||||
m_passthruSessTmo = sessTmoMilli;
|
||||
|
||||
// Set the reaper thread wakeup interval
|
||||
|
||||
m_reaperThread.setWakeup( sessTmoMilli / 2);
|
||||
}
|
||||
catch(NumberFormatException ex)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Invalid authenication session timeout value");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the person service
|
||||
*
|
||||
* @param personService PersonService
|
||||
*/
|
||||
public final void setPersonService(PersonService personService)
|
||||
{
|
||||
m_personService = personService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the node service
|
||||
*
|
||||
* @param nodeService NodeService
|
||||
*/
|
||||
public final void setNodeService(NodeService nodeService)
|
||||
{
|
||||
m_nodeService = nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the authentication session timeout, in milliseconds
|
||||
*
|
||||
* @return long
|
||||
*/
|
||||
private final long getSessionTimeout()
|
||||
{
|
||||
return m_passthruSessTmo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate
|
||||
*
|
||||
* @param userName String
|
||||
* @param password char[]
|
||||
* @throws AuthenticationException
|
||||
*/
|
||||
public void authenticate(String userName, char[] password) throws AuthenticationException
|
||||
{
|
||||
// Debug
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Authenticate user=" + userName + " via local credentials");
|
||||
|
||||
// Create a local authentication token
|
||||
|
||||
NTLMLocalToken authToken = new NTLMLocalToken(userName, new String(password));
|
||||
|
||||
// Authenticate using the token
|
||||
|
||||
authenticate( authToken);
|
||||
setCurrentUser( userName.toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate using a token
|
||||
*
|
||||
* @param token Authentication
|
||||
* @return Authentication
|
||||
* @throws AuthenticationException
|
||||
*/
|
||||
public Authentication authenticate(Authentication auth) throws AuthenticationException
|
||||
{
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Authenticate " + auth + " via token");
|
||||
|
||||
// Check if the token is for passthru authentication
|
||||
|
||||
if( auth instanceof NTLMPassthruToken)
|
||||
{
|
||||
// Access the NTLM passthru token
|
||||
|
||||
NTLMPassthruToken ntlmToken = (NTLMPassthruToken) auth;
|
||||
|
||||
// Authenticate using passthru
|
||||
|
||||
authenticatePassthru(ntlmToken);
|
||||
}
|
||||
|
||||
// Check for a local authentication token
|
||||
|
||||
else if( auth instanceof NTLMLocalToken)
|
||||
{
|
||||
AuthenticateSession authSess = null;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
// Access the NTLM token
|
||||
|
||||
NTLMLocalToken ntlmToken = (NTLMLocalToken) auth;
|
||||
|
||||
// Open a session to an authentication server
|
||||
|
||||
authSess = m_passthruServers.openSession();
|
||||
|
||||
// Authenticate using the credentials supplied
|
||||
|
||||
authenticateLocal(ntlmToken, authSess);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Make sure the authentication session is closed
|
||||
|
||||
if ( authSess != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
authSess.CloseSession();
|
||||
}
|
||||
catch ( Exception ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unsupported authentication token
|
||||
|
||||
throw new AuthenticationException("Unsupported authentication token type");
|
||||
}
|
||||
|
||||
// Return the updated authentication token
|
||||
|
||||
return getCurrentAuthentication();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the enum that describes NTLM integration
|
||||
*
|
||||
* @return NTLMMode
|
||||
*/
|
||||
public NTLMMode getNTLMMode()
|
||||
{
|
||||
return NTLMMode.PASS_THROUGH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MD4 password hash, as required by NTLM based authentication methods.
|
||||
*
|
||||
* @param userName String
|
||||
* @return String
|
||||
*/
|
||||
public String getMD4HashedPassword(String userName)
|
||||
{
|
||||
// Do not support MD4 hashed password
|
||||
|
||||
throw new AlfrescoRuntimeException("MD4 passwords not supported");
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate a user using local credentials
|
||||
*
|
||||
* @param ntlmToken NTLMLocalToken
|
||||
* @param authSess AuthenticateSession
|
||||
*/
|
||||
private void authenticateLocal(NTLMLocalToken ntlmToken, AuthenticateSession authSess)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get the plaintext password and generate an NTLM1 password hash
|
||||
|
||||
String username = (String) ntlmToken.getPrincipal();
|
||||
String plainPwd = (String) ntlmToken.getCredentials();
|
||||
byte[] ntlm1Pwd = m_encryptor.generateEncryptedPassword( plainPwd, authSess.getEncryptionKey(), PasswordEncryptor.NTLM1);
|
||||
|
||||
// Send the logon request to the authentication server
|
||||
//
|
||||
// Note: Only use the stronger NTLM hash, we do not send the LM hash
|
||||
|
||||
authSess.doSessionSetup(username, null, ntlm1Pwd);
|
||||
|
||||
// Check if the session has logged on as a guest
|
||||
|
||||
if ( authSess.isGuest() || username.equalsIgnoreCase("GUEST"))
|
||||
{
|
||||
// If guest access is enabled add a guest authority to the token
|
||||
|
||||
if ( allowsGuest())
|
||||
{
|
||||
// Set the guest authority
|
||||
|
||||
GrantedAuthority[] authorities = new GrantedAuthority[2];
|
||||
authorities[0] = new GrantedAuthorityImpl(NTLMAuthorityGuest);
|
||||
authorities[1] = new GrantedAuthorityImpl("ROLE_AUTHENTICATED");
|
||||
|
||||
ntlmToken.setAuthorities(authorities);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Guest access not allowed
|
||||
|
||||
throw new AuthenticationException("Guest logons disabled");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set authorities
|
||||
|
||||
GrantedAuthority[] authorities = new GrantedAuthority[1];
|
||||
authorities[0] = new GrantedAuthorityImpl("ROLE_AUTHENTICATED");
|
||||
|
||||
ntlmToken.setAuthorities(authorities);
|
||||
}
|
||||
|
||||
// Indicate that the token is authenticated
|
||||
|
||||
ntlmToken.setAuthenticated(true);
|
||||
|
||||
// Map the passthru username to an Alfresco person
|
||||
|
||||
NodeRef userNode = m_personService.getPerson(username);
|
||||
if ( userNode != null)
|
||||
{
|
||||
// Get the person name and use that as the current user to line up with permission checks
|
||||
|
||||
String personName = (String) m_nodeService.getProperty(userNode, ContentModel.PROP_USERNAME);
|
||||
setCurrentUser(personName);
|
||||
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Setting current user using person " + personName + " (username " + username + ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set using the user name, lowercase the name if hte person service is case insensitive
|
||||
|
||||
if ( m_personService.getUserNamesAreCaseSensitive() == false)
|
||||
username = username.toLowerCase();
|
||||
setCurrentUser( username);
|
||||
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Setting current user using username " + username);
|
||||
}
|
||||
|
||||
// Debug
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Authenticated token=" + ntlmToken);
|
||||
}
|
||||
catch (NoSuchAlgorithmException ex)
|
||||
{
|
||||
// JCE provider does not have the required encryption/hashing algorithms
|
||||
|
||||
throw new AuthenticationServiceException("JCE provider error", ex);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
// Error connecting to the authentication server
|
||||
|
||||
throw new AuthenticationServiceException("I/O error", ex);
|
||||
}
|
||||
catch (SMBException ex)
|
||||
{
|
||||
// Check the returned status code to determine why the logon failed and throw an appropriate exception
|
||||
|
||||
if ( ex.getErrorClass() == SMBStatus.NTErr)
|
||||
{
|
||||
AuthenticationException authEx = null;
|
||||
|
||||
switch( ex.getErrorCode())
|
||||
{
|
||||
case SMBStatus.NTLogonFailure:
|
||||
authEx = new AuthenticationException("Logon failure");
|
||||
break;
|
||||
case SMBStatus.NTAccountDisabled:
|
||||
authEx = new AuthenticationException("Account disabled");
|
||||
break;
|
||||
default:
|
||||
authEx = new AuthenticationException("Logon failure");
|
||||
break;
|
||||
}
|
||||
|
||||
throw authEx;
|
||||
}
|
||||
else
|
||||
throw new AuthenticationException("Logon failure");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate using passthru authentication with a client
|
||||
*
|
||||
* @param ntlmToken NTLMPassthruToken
|
||||
*/
|
||||
private void authenticatePassthru(NTLMPassthruToken ntlmToken)
|
||||
{
|
||||
// Check if the token has an authentication session, if not then it is either a new token
|
||||
// or the session has been timed out
|
||||
|
||||
AuthenticateSession authSess = m_passthruSessions.get(ntlmToken);
|
||||
|
||||
if ( authSess == null)
|
||||
{
|
||||
// Check if the token has a challenge, if it does then the associated session has been
|
||||
// timed out
|
||||
|
||||
if ( ntlmToken.getChallenge() != null)
|
||||
throw new CredentialsExpiredException("Authentication session expired");
|
||||
|
||||
// Open an authentication session for the new token and add to the active session list
|
||||
|
||||
authSess = m_passthruServers.openSession();
|
||||
|
||||
ntlmToken.setAuthenticationExpireTime(System.currentTimeMillis() + getSessionTimeout());
|
||||
|
||||
// Get the challenge from the initial session negotiate stage
|
||||
|
||||
ntlmToken.setChallenge(new NTLMChallenge(authSess.getEncryptionKey()));
|
||||
|
||||
StringBuilder details = new StringBuilder();
|
||||
|
||||
// Build a details string with the authentication session details
|
||||
|
||||
details.append(authSess.getDomain());
|
||||
details.append("\\");
|
||||
details.append(authSess.getPCShare().getNodeName());
|
||||
details.append(",");
|
||||
details.append(authSess.getSession().getProtocolName());
|
||||
|
||||
ntlmToken.setDetails(details.toString());
|
||||
|
||||
// Put the token/session into the active session list
|
||||
|
||||
m_passthruSessions.put(ntlmToken, authSess);
|
||||
|
||||
// Debug
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Passthru stage 1 token " + ntlmToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
// Stage two of the authentication, send the hashed password to the authentication server
|
||||
|
||||
byte[] lmPwd = null;
|
||||
byte[] ntlmPwd = null;
|
||||
|
||||
if ( ntlmToken.getPasswordType() == PasswordEncryptor.LANMAN)
|
||||
lmPwd = ntlmToken.getHashedPassword();
|
||||
else if ( ntlmToken.getPasswordType() == PasswordEncryptor.NTLM1)
|
||||
ntlmPwd = ntlmToken.getHashedPassword();
|
||||
|
||||
String username = (String) ntlmToken.getPrincipal();
|
||||
|
||||
authSess.doSessionSetup(username, lmPwd, ntlmPwd);
|
||||
|
||||
// Check if the session has logged on as a guest
|
||||
|
||||
if ( authSess.isGuest() || username.equalsIgnoreCase("GUEST"))
|
||||
{
|
||||
// If guest access is enabled add a guest authority to the token
|
||||
|
||||
if ( allowsGuest())
|
||||
{
|
||||
// Set the guest authority
|
||||
|
||||
GrantedAuthority[] authorities = new GrantedAuthority[1];
|
||||
authorities[0] = new GrantedAuthorityImpl(NTLMAuthorityGuest);
|
||||
|
||||
ntlmToken.setAuthorities(authorities);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Guest access not allowed
|
||||
|
||||
throw new BadCredentialsException("Guest logons disabled");
|
||||
}
|
||||
}
|
||||
|
||||
// Indicate that the token is authenticated
|
||||
|
||||
ntlmToken.setAuthenticated(true);
|
||||
|
||||
// Map the passthru username to an Alfresco person
|
||||
|
||||
NodeRef userNode = m_personService.getPerson(username);
|
||||
if ( userNode != null)
|
||||
{
|
||||
// Get the person name and use that as the current user to line up with permission checks
|
||||
|
||||
String personName = (String) m_nodeService.getProperty(userNode, ContentModel.PROP_USERNAME);
|
||||
setCurrentUser(personName);
|
||||
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Setting current user using person " + personName + " (username " + username + ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set using the user name, lowercase the name if the person service is case insensitive
|
||||
|
||||
if ( m_personService.getUserNamesAreCaseSensitive() == false)
|
||||
username = username.toLowerCase();
|
||||
setCurrentUser( username);
|
||||
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Setting current user using username " + username);
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
// Error connecting to the authentication server
|
||||
|
||||
throw new AuthenticationServiceException("I/O error", ex);
|
||||
}
|
||||
catch (SMBException ex)
|
||||
{
|
||||
// Debug
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Passthru exception, " + ex);
|
||||
|
||||
// Check the returned status code to determine why the logon failed and throw an appropriate exception
|
||||
|
||||
if ( ex.getErrorClass() == SMBStatus.NTErr)
|
||||
{
|
||||
AuthenticationException authEx = null;
|
||||
|
||||
switch( ex.getErrorCode())
|
||||
{
|
||||
case SMBStatus.NTLogonFailure:
|
||||
authEx = new AuthenticationException("Logon failure");
|
||||
break;
|
||||
case SMBStatus.NTAccountDisabled:
|
||||
authEx = new AuthenticationException("Account disabled");
|
||||
break;
|
||||
default:
|
||||
authEx = new AuthenticationException("Logon failure");
|
||||
break;
|
||||
}
|
||||
|
||||
throw authEx;
|
||||
}
|
||||
else
|
||||
throw new BadCredentialsException("Logon failure");
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Make sure the authentication session is closed
|
||||
|
||||
if ( authSess != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Remove the session from the active list
|
||||
|
||||
m_passthruSessions.remove(ntlmToken);
|
||||
|
||||
// Close the session to the authentication server
|
||||
|
||||
authSess.CloseSession();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the user exists
|
||||
*
|
||||
* @param userName String
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean exists(String userName)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean implementationAllowsGuestLogin()
|
||||
{
|
||||
return allowsGuest();
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,755 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Alfresco Network License. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfrescosoftware.com/legal/
|
||||
*
|
||||
* Please view the license relevant to your network subscription.
|
||||
*
|
||||
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
|
||||
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
|
||||
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
|
||||
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
|
||||
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
|
||||
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
|
||||
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
|
||||
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
|
||||
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
|
||||
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
|
||||
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
|
||||
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.ntlm;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.Provider;
|
||||
import java.security.Security;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.filesys.server.auth.PasswordEncryptor;
|
||||
import org.alfresco.filesys.server.auth.passthru.AuthenticateSession;
|
||||
import org.alfresco.filesys.server.auth.passthru.PassthruServers;
|
||||
import org.alfresco.filesys.smb.SMBException;
|
||||
import org.alfresco.filesys.smb.SMBStatus;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import net.sf.acegisecurity.*;
|
||||
import net.sf.acegisecurity.providers.*;
|
||||
|
||||
/**
|
||||
* NTLM Authentication Provider
|
||||
*
|
||||
* @author GKSpencer
|
||||
*/
|
||||
public class NTLMAuthenticationProvider implements AuthenticationProvider
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog("org.alfresco.acegi");
|
||||
|
||||
// Constants
|
||||
//
|
||||
// Standard authorities
|
||||
|
||||
public static final String NTLMAuthorityGuest = "Guest";
|
||||
public static final String NTLMAuthorityAdministrator = "Administrator";
|
||||
|
||||
// Active session timeout
|
||||
|
||||
private static final long DefaultSessionTimeout = 60000L; // 1 minute
|
||||
private static final long MinimumSessionTimeout = 5000L; // 5 seconds
|
||||
|
||||
// Passthru authentication servers
|
||||
|
||||
private PassthruServers m_passthruServers;
|
||||
|
||||
// Password encryptor for generating password hash for local authentication
|
||||
|
||||
private PasswordEncryptor m_encryptor;
|
||||
|
||||
// Allow guest access
|
||||
|
||||
private boolean m_allowGuest;
|
||||
|
||||
// Table of currently active passthru authentications and the associated authentication session
|
||||
//
|
||||
// If the two authentication stages are not completed within a reasonable time the authentication
|
||||
// session will be closed by the reaper thread.
|
||||
|
||||
private Hashtable<NTLMPassthruToken,AuthenticateSession> m_passthruSessions;
|
||||
|
||||
// Active authentication session timeout, in milliseconds
|
||||
|
||||
private long m_passthruSessTmo = DefaultSessionTimeout;
|
||||
|
||||
// Authentication session reaper thread
|
||||
|
||||
private PassthruReaperThread m_reaperThread;
|
||||
|
||||
/**
|
||||
* Passthru Session Repear Thread
|
||||
*/
|
||||
class PassthruReaperThread extends Thread
|
||||
{
|
||||
// Thread shutdown request flag
|
||||
|
||||
private boolean m_ishutdown;
|
||||
|
||||
// Reaper wakeup interval, in milliseconds
|
||||
|
||||
private long m_wakeupInterval = m_passthruSessTmo / 2;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
PassthruReaperThread()
|
||||
{
|
||||
setDaemon(true);
|
||||
setName("PassthruReaper");
|
||||
start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the wakeup interval
|
||||
*
|
||||
* @param wakeup long
|
||||
*/
|
||||
public final void setWakeup(long wakeup)
|
||||
{
|
||||
m_wakeupInterval = wakeup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main thread code
|
||||
*/
|
||||
public void run()
|
||||
{
|
||||
// Loop until shutdown
|
||||
|
||||
m_ishutdown = false;
|
||||
|
||||
while ( m_ishutdown == false)
|
||||
{
|
||||
// Sleep for a while
|
||||
|
||||
try
|
||||
{
|
||||
sleep( m_wakeupInterval);
|
||||
}
|
||||
catch ( InterruptedException ex)
|
||||
{
|
||||
}
|
||||
|
||||
// Check if there are any active sessions to check
|
||||
|
||||
if ( m_passthruSessions.size() > 0)
|
||||
{
|
||||
// Enumerate the active sessions
|
||||
|
||||
Enumeration<NTLMPassthruToken> tokenEnum = m_passthruSessions.keys();
|
||||
long timeNow = System.currentTimeMillis();
|
||||
|
||||
while (tokenEnum.hasMoreElements())
|
||||
{
|
||||
// Get the current NTLM token and check if it has expired
|
||||
|
||||
NTLMPassthruToken ntlmToken = tokenEnum.nextElement();
|
||||
|
||||
if ( ntlmToken != null && ntlmToken.getAuthenticationExpireTime() < timeNow)
|
||||
{
|
||||
// Authentication token has expired, close the associated authentication session
|
||||
|
||||
AuthenticateSession authSess = m_passthruSessions.get(ntlmToken);
|
||||
if ( authSess != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Close the authentication session
|
||||
|
||||
authSess.CloseSession();
|
||||
}
|
||||
catch ( Exception ex)
|
||||
{
|
||||
// Debug
|
||||
|
||||
if(logger.isDebugEnabled())
|
||||
logger.debug("Error closing expired authentication session", ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the expired token from the active list
|
||||
|
||||
m_passthruSessions.remove(ntlmToken);
|
||||
|
||||
// Debug
|
||||
|
||||
if(logger.isDebugEnabled())
|
||||
logger.debug("Removed expired NTLM token " + ntlmToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Debug
|
||||
|
||||
if(logger.isDebugEnabled())
|
||||
logger.debug("Passthru reaper thread shutdown");
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown the reaper thread
|
||||
*/
|
||||
public final void shutdownRequest()
|
||||
{
|
||||
m_ishutdown = true;
|
||||
this.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*/
|
||||
public NTLMAuthenticationProvider() {
|
||||
|
||||
// Create the passthru authentication server list
|
||||
|
||||
m_passthruServers = new PassthruServers();
|
||||
|
||||
// Create the password encryptor for local password hashing
|
||||
|
||||
m_encryptor = new PasswordEncryptor();
|
||||
|
||||
// Create the active session list and reaper thread
|
||||
|
||||
m_passthruSessions = new Hashtable<NTLMPassthruToken,AuthenticateSession>();
|
||||
m_reaperThread = new PassthruReaperThread();
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate a user
|
||||
*
|
||||
* @param auth Authentication
|
||||
* @return Authentication
|
||||
* @exception AuthenticationException
|
||||
*/
|
||||
public Authentication authenticate(Authentication auth) throws AuthenticationException
|
||||
{
|
||||
// DEBUG
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Authenticate " + auth);
|
||||
|
||||
// Check if the token is for passthru authentication
|
||||
|
||||
if( auth instanceof NTLMPassthruToken)
|
||||
{
|
||||
// Access the NTLM passthru token
|
||||
|
||||
NTLMPassthruToken ntlmToken = (NTLMPassthruToken) auth;
|
||||
|
||||
// Authenticate using passthru
|
||||
|
||||
authenticatePassthru(ntlmToken);
|
||||
}
|
||||
|
||||
// Check for a local authentication token
|
||||
|
||||
else if( auth instanceof NTLMLocalToken)
|
||||
{
|
||||
AuthenticateSession authSess = null;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
// Access the NTLM token
|
||||
|
||||
NTLMLocalToken ntlmToken = (NTLMLocalToken) auth;
|
||||
|
||||
// Open a session to an authentication server
|
||||
|
||||
authSess = m_passthruServers.openSession();
|
||||
|
||||
// Authenticate using the credentials supplied
|
||||
|
||||
authenticateLocal(ntlmToken, authSess);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Make sure the authentication session is closed
|
||||
|
||||
if ( authSess != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
authSess.CloseSession();
|
||||
}
|
||||
catch ( Exception ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the updated authentication token
|
||||
|
||||
return auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this provider supports the specified authentication token
|
||||
*
|
||||
* @param authentication Class
|
||||
*/
|
||||
public boolean supports(Class authentication)
|
||||
{
|
||||
// Check if the authentication is an NTLM authentication token
|
||||
|
||||
if ( NTLMPassthruToken.class.isAssignableFrom(authentication))
|
||||
return true;
|
||||
return NTLMLocalToken.class.isAssignableFrom(authentication);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if guest logons are allowed
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean allowsGuest()
|
||||
{
|
||||
return m_allowGuest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the domain to authenticate against
|
||||
*
|
||||
* @param domain String
|
||||
*/
|
||||
public final void setDomain(String domain) {
|
||||
|
||||
// Check if the passthru server list is already configured
|
||||
|
||||
if ( m_passthruServers.getTotalServerCount() > 0)
|
||||
throw new AlfrescoRuntimeException("Passthru server list already configured");
|
||||
|
||||
// Configure the passthru authentication server list using the domain controllers
|
||||
|
||||
m_passthruServers.setDomain(domain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the server(s) to authenticate against
|
||||
*
|
||||
* @param servers String
|
||||
*/
|
||||
public final void setServers(String servers) {
|
||||
|
||||
// Check if the passthru server list is already configured
|
||||
|
||||
if ( m_passthruServers.getTotalServerCount() > 0)
|
||||
throw new AlfrescoRuntimeException("Passthru server list already configured");
|
||||
|
||||
// Configure the passthru authenticaiton list using a list of server names/addresses
|
||||
|
||||
m_passthruServers.setServerList(servers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the local server as the authentication server
|
||||
*
|
||||
* @param useLocal String
|
||||
*/
|
||||
public final void setUseLocalServer(String useLocal)
|
||||
{
|
||||
// Check if the local server should be used for authentication
|
||||
|
||||
if ( Boolean.parseBoolean(useLocal) == true)
|
||||
{
|
||||
// Check if the passthru server list is already configured
|
||||
|
||||
if ( m_passthruServers.getTotalServerCount() > 0)
|
||||
throw new AlfrescoRuntimeException("Passthru server list already configured");
|
||||
|
||||
try
|
||||
{
|
||||
// Get the list of local network addresses
|
||||
|
||||
InetAddress[] localAddrs = InetAddress.getAllByName(InetAddress.getLocalHost().getHostName());
|
||||
|
||||
// Build the list of local addresses
|
||||
|
||||
if ( localAddrs != null && localAddrs.length > 0)
|
||||
{
|
||||
StringBuilder addrStr = new StringBuilder();
|
||||
|
||||
for ( InetAddress curAddr : localAddrs)
|
||||
{
|
||||
if ( curAddr.isLoopbackAddress() == false)
|
||||
{
|
||||
addrStr.append(curAddr.getHostAddress());
|
||||
addrStr.append(",");
|
||||
}
|
||||
}
|
||||
|
||||
if ( addrStr.length() > 0)
|
||||
addrStr.setLength(addrStr.length() - 1);
|
||||
|
||||
// Set the server list using the local address list
|
||||
|
||||
m_passthruServers.setServerList(addrStr.toString());
|
||||
}
|
||||
else
|
||||
throw new AlfrescoRuntimeException("No local server address(es)");
|
||||
}
|
||||
catch ( UnknownHostException ex)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Failed to get local address list");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow guest access
|
||||
*
|
||||
* @param guest String
|
||||
*/
|
||||
public final void setGuestAccess(String guest)
|
||||
{
|
||||
m_allowGuest = Boolean.parseBoolean(guest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JCE provider
|
||||
*
|
||||
* @param providerClass String
|
||||
*/
|
||||
public final void setJCEProvider(String providerClass)
|
||||
{
|
||||
// Set the JCE provider, required to provide various encryption/hashing algorithms not available
|
||||
// in the standard Sun JDK/JRE
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
// Load the JCE provider class and validate
|
||||
|
||||
Object jceObj = Class.forName(providerClass).newInstance();
|
||||
if (jceObj instanceof java.security.Provider)
|
||||
{
|
||||
|
||||
// Inform listeners, validate the configuration change
|
||||
|
||||
Provider jceProvider = (Provider) jceObj;
|
||||
|
||||
// Add the JCE provider
|
||||
|
||||
Security.addProvider(jceProvider);
|
||||
|
||||
// Debug
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Using JCE provider " + providerClass);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AlfrescoRuntimeException("JCE provider class is not a valid Provider class");
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException ex)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("JCE provider class " + providerClass + " not found");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("JCE provider class error", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the authentication session timeout, in seconds
|
||||
*
|
||||
* @param sessTmo String
|
||||
*/
|
||||
public final void setSessionTimeout(String sessTmo)
|
||||
{
|
||||
// Convert to an integer value and range check the timeout value
|
||||
|
||||
try
|
||||
{
|
||||
// Convert to an integer value
|
||||
|
||||
long sessTmoMilli = Long.parseLong(sessTmo) * 1000L;
|
||||
|
||||
if ( sessTmoMilli < MinimumSessionTimeout)
|
||||
throw new AlfrescoRuntimeException("Authentication session timeout too low, " + sessTmo);
|
||||
|
||||
// Set the authentication session timeout value
|
||||
|
||||
m_passthruSessTmo = sessTmoMilli;
|
||||
|
||||
// Set the reaper thread wakeup interval
|
||||
|
||||
m_reaperThread.setWakeup( sessTmoMilli / 2);
|
||||
}
|
||||
catch(NumberFormatException ex)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Invalid authenication session timeout value");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the authentication session timeout, in milliseconds
|
||||
*
|
||||
* @return long
|
||||
*/
|
||||
private final long getSessionTimeout()
|
||||
{
|
||||
return m_passthruSessTmo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate a user using local credentials
|
||||
*
|
||||
* @param ntlmToken NTLMLocalToken
|
||||
* @param authSess AuthenticateSession
|
||||
*/
|
||||
private void authenticateLocal(NTLMLocalToken ntlmToken, AuthenticateSession authSess)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get the plaintext password and generate an NTLM1 password hash
|
||||
|
||||
String username = (String) ntlmToken.getPrincipal();
|
||||
String plainPwd = (String) ntlmToken.getCredentials();
|
||||
byte[] ntlm1Pwd = m_encryptor.generateEncryptedPassword( plainPwd, authSess.getEncryptionKey(), PasswordEncryptor.NTLM1);
|
||||
|
||||
// Send the logon request to the authentication server
|
||||
//
|
||||
// Note: Only use the stronger NTLM hash, we do not send the LM hash
|
||||
|
||||
authSess.doSessionSetup(username, null, ntlm1Pwd);
|
||||
|
||||
// Check if the session has logged on as a guest
|
||||
|
||||
if ( authSess.isGuest() || username.equalsIgnoreCase("GUEST"))
|
||||
{
|
||||
// If guest access is enabled add a guest authority to the token
|
||||
|
||||
if ( allowsGuest())
|
||||
{
|
||||
// Set the guest authority
|
||||
|
||||
GrantedAuthority[] authorities = new GrantedAuthority[1];
|
||||
authorities[0] = new GrantedAuthorityImpl(NTLMAuthorityGuest);
|
||||
|
||||
ntlmToken.setAuthorities(authorities);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Guest access not allowed
|
||||
|
||||
throw new BadCredentialsException("Guest logons disabled");
|
||||
}
|
||||
}
|
||||
|
||||
// Indicate that the token is authenticated
|
||||
|
||||
ntlmToken.setAuthenticated(true);
|
||||
}
|
||||
catch (NoSuchAlgorithmException ex)
|
||||
{
|
||||
// JCE provider does not have the required encryption/hashing algorithms
|
||||
|
||||
throw new AuthenticationServiceException("JCE provider error", ex);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
// Error connecting to the authentication server
|
||||
|
||||
throw new AuthenticationServiceException("I/O error", ex);
|
||||
}
|
||||
catch (SMBException ex)
|
||||
{
|
||||
// Check the returned status code to determine why the logon failed and throw an appropriate exception
|
||||
|
||||
if ( ex.getErrorClass() == SMBStatus.NTErr)
|
||||
{
|
||||
AuthenticationException authEx = null;
|
||||
|
||||
switch( ex.getErrorCode())
|
||||
{
|
||||
case SMBStatus.NTLogonFailure:
|
||||
authEx = new BadCredentialsException("Logon failure");
|
||||
break;
|
||||
case SMBStatus.NTAccountDisabled:
|
||||
authEx = new DisabledException("Account disabled");
|
||||
break;
|
||||
default:
|
||||
authEx = new BadCredentialsException("Logon failure");
|
||||
break;
|
||||
}
|
||||
|
||||
throw authEx;
|
||||
}
|
||||
else
|
||||
throw new BadCredentialsException("Logon failure");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate using passthru authentication with a client
|
||||
*
|
||||
* @param ntlmToken NTLMPassthruToken
|
||||
*/
|
||||
private void authenticatePassthru(NTLMPassthruToken ntlmToken)
|
||||
{
|
||||
// Check if the token has an authentication session, if not then it is either a new token
|
||||
// or the session has been timed out
|
||||
|
||||
AuthenticateSession authSess = m_passthruSessions.get(ntlmToken);
|
||||
|
||||
if ( authSess == null)
|
||||
{
|
||||
// Check if the token has a challenge, if it does then the associated session has been
|
||||
// timed out
|
||||
|
||||
if ( ntlmToken.getChallenge() != null)
|
||||
throw new CredentialsExpiredException("Authentication session expired");
|
||||
|
||||
// Open an authentication session for the new token and add to the active session list
|
||||
|
||||
authSess = m_passthruServers.openSession();
|
||||
|
||||
ntlmToken.setAuthenticationExpireTime(System.currentTimeMillis() + getSessionTimeout());
|
||||
|
||||
// Get the challenge from the initial session negotiate stage
|
||||
|
||||
ntlmToken.setChallenge(new NTLMChallenge(authSess.getEncryptionKey()));
|
||||
|
||||
StringBuilder details = new StringBuilder();
|
||||
|
||||
// Build a details string with the authentication session details
|
||||
|
||||
details.append(authSess.getDomain());
|
||||
details.append("\\");
|
||||
details.append(authSess.getPCShare().getNodeName());
|
||||
details.append(",");
|
||||
details.append(authSess.getSession().getProtocolName());
|
||||
|
||||
ntlmToken.setDetails(details.toString());
|
||||
|
||||
// Put the token/session into the active session list
|
||||
|
||||
m_passthruSessions.put(ntlmToken, authSess);
|
||||
|
||||
// Debug
|
||||
|
||||
if ( logger.isDebugEnabled())
|
||||
logger.debug("Passthru stage 1 token " + ntlmToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
// Stage two of the authentication, send the hashed password to the authentication server
|
||||
|
||||
byte[] lmPwd = null;
|
||||
byte[] ntlmPwd = null;
|
||||
|
||||
if ( ntlmToken.getPasswordType() == PasswordEncryptor.LANMAN)
|
||||
lmPwd = ntlmToken.getHashedPassword();
|
||||
else if ( ntlmToken.getPasswordType() == PasswordEncryptor.NTLM1)
|
||||
ntlmPwd = ntlmToken.getHashedPassword();
|
||||
|
||||
String username = (String) ntlmToken.getPrincipal();
|
||||
|
||||
authSess.doSessionSetup(username, lmPwd, ntlmPwd);
|
||||
|
||||
// Check if the session has logged on as a guest
|
||||
|
||||
if ( authSess.isGuest() || username.equalsIgnoreCase("GUEST"))
|
||||
{
|
||||
// If guest access is enabled add a guest authority to the token
|
||||
|
||||
if ( allowsGuest())
|
||||
{
|
||||
// Set the guest authority
|
||||
|
||||
GrantedAuthority[] authorities = new GrantedAuthority[1];
|
||||
authorities[0] = new GrantedAuthorityImpl(NTLMAuthorityGuest);
|
||||
|
||||
ntlmToken.setAuthorities(authorities);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Guest access not allowed
|
||||
|
||||
throw new BadCredentialsException("Guest logons disabled");
|
||||
}
|
||||
}
|
||||
|
||||
// Indicate that the token is authenticated
|
||||
|
||||
ntlmToken.setAuthenticated(true);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
// Error connecting to the authentication server
|
||||
|
||||
throw new AuthenticationServiceException("I/O error", ex);
|
||||
}
|
||||
catch (SMBException ex)
|
||||
{
|
||||
// Check the returned status code to determine why the logon failed and throw an appropriate exception
|
||||
|
||||
if ( ex.getErrorClass() == SMBStatus.NTErr)
|
||||
{
|
||||
AuthenticationException authEx = null;
|
||||
|
||||
switch( ex.getErrorCode())
|
||||
{
|
||||
case SMBStatus.NTLogonFailure:
|
||||
authEx = new BadCredentialsException("Logon failure");
|
||||
break;
|
||||
case SMBStatus.NTAccountDisabled:
|
||||
authEx = new DisabledException("Account disabled");
|
||||
break;
|
||||
default:
|
||||
authEx = new BadCredentialsException("Logon failure");
|
||||
break;
|
||||
}
|
||||
|
||||
throw authEx;
|
||||
}
|
||||
else
|
||||
throw new BadCredentialsException("Logon failure");
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Make sure the authentication session is closed
|
||||
|
||||
if ( authSess != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Remove the session from the active list
|
||||
|
||||
m_passthruSessions.remove(ntlmToken);
|
||||
|
||||
// Close the session to the authentication server
|
||||
|
||||
authSess.CloseSession();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Alfresco Network License. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfrescosoftware.com/legal/
|
||||
*
|
||||
* Please view the license relevant to your network subscription.
|
||||
*
|
||||
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
|
||||
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
|
||||
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
|
||||
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
|
||||
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
|
||||
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
|
||||
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
|
||||
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
|
||||
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
|
||||
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
|
||||
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
|
||||
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.ntlm;
|
||||
|
||||
import org.alfresco.filesys.util.HexDump;
|
||||
|
||||
/**
|
||||
* Contains the NTLM challenge bytes.
|
||||
*
|
||||
* @author GKSpencer
|
||||
*/
|
||||
public class NTLMChallenge
|
||||
{
|
||||
// Challenge bytes
|
||||
|
||||
private byte[] m_challenge;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param chbyts byte[]
|
||||
*/
|
||||
protected NTLMChallenge(byte[] chbyts)
|
||||
{
|
||||
m_challenge = chbyts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the challenge bytes
|
||||
*
|
||||
* @return byte[]
|
||||
*/
|
||||
public final byte[] getBytes()
|
||||
{
|
||||
return m_challenge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for object equality
|
||||
*
|
||||
* @param obj Object
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if ( obj instanceof NTLMChallenge)
|
||||
{
|
||||
NTLMChallenge ntlmCh = (NTLMChallenge) obj;
|
||||
|
||||
// Check if both challenges are null
|
||||
|
||||
if ( getBytes() == null && ntlmCh.getBytes() == null)
|
||||
return true;
|
||||
|
||||
// Check if both challenges are the same length
|
||||
|
||||
if ( getBytes() != null && ntlmCh.getBytes() != null &&
|
||||
getBytes().length == ntlmCh.getBytes().length)
|
||||
{
|
||||
// Check if challenages are the same value
|
||||
|
||||
byte[] ntlmBytes = ntlmCh.getBytes();
|
||||
|
||||
for ( int i = 0; i < m_challenge.length; i++)
|
||||
if ( m_challenge[i] != ntlmBytes[i])
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// Not the same type
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the challenge as a string
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder str = new StringBuilder();
|
||||
|
||||
str.append("[");
|
||||
str.append(HexDump.hexString(getBytes(), " "));
|
||||
str.append("]");
|
||||
|
||||
return str.toString();
|
||||
}
|
||||
}
|
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Alfresco Network License. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfrescosoftware.com/legal/
|
||||
*
|
||||
* Please view the license relevant to your network subscription.
|
||||
*
|
||||
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
|
||||
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
|
||||
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
|
||||
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
|
||||
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
|
||||
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
|
||||
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
|
||||
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
|
||||
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
|
||||
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
|
||||
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
|
||||
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.ntlm;
|
||||
|
||||
import net.sf.acegisecurity.GrantedAuthority;
|
||||
import net.sf.acegisecurity.providers.*;
|
||||
|
||||
/**
|
||||
* <p>Used to provide authentication with a remote Windows server when the username and password are
|
||||
* provided locally.
|
||||
*
|
||||
* @author GKSpencer
|
||||
*/
|
||||
public class NTLMLocalToken extends UsernamePasswordAuthenticationToken
|
||||
{
|
||||
private static final long serialVersionUID = -7946514578455279387L;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*/
|
||||
protected NTLMLocalToken()
|
||||
{
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param username String
|
||||
* @param plainPwd String
|
||||
*/
|
||||
public NTLMLocalToken(String username, String plainPwd) {
|
||||
super(username.toLowerCase(), plainPwd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the user logged on as a guest
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean isGuestLogon()
|
||||
{
|
||||
return hasAuthority(NTLMAuthenticationProvider.NTLMAuthorityGuest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the user is an administrator
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean isAdministrator()
|
||||
{
|
||||
return hasAuthority(NTLMAuthenticationProvider.NTLMAuthorityAdministrator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for the specified authority
|
||||
*
|
||||
* @param authority String
|
||||
* @return boolean
|
||||
*/
|
||||
public final boolean hasAuthority(String authority)
|
||||
{
|
||||
boolean found = false;
|
||||
GrantedAuthority[] authorities = getAuthorities();
|
||||
|
||||
if ( authorities != null && authorities.length > 0)
|
||||
{
|
||||
// Search for the specified authority
|
||||
|
||||
int i = 0;
|
||||
|
||||
while ( found == false && i < authorities.length)
|
||||
{
|
||||
if ( authorities[i++].getAuthority().equals(authority))
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the status
|
||||
|
||||
return found;
|
||||
}
|
||||
}
|
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Alfresco Network License. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfrescosoftware.com/legal/
|
||||
*
|
||||
* Please view the license relevant to your network subscription.
|
||||
*
|
||||
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
|
||||
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
|
||||
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
|
||||
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
|
||||
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
|
||||
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
|
||||
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
|
||||
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
|
||||
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
|
||||
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
|
||||
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
|
||||
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.ntlm;
|
||||
|
||||
/**
|
||||
* <p>Used to provide passthru authentication to a remote Windows server using multiple stages that
|
||||
* allows authentication details to be passed between a client and the remote authenticating server without
|
||||
* the password being known by the authentication provider.
|
||||
*
|
||||
* @author GKSpencer
|
||||
*/
|
||||
public class NTLMPassthruToken extends NTLMLocalToken
|
||||
{
|
||||
private static final long serialVersionUID = -4635444888514735368L;
|
||||
|
||||
// Challenge for this session
|
||||
|
||||
private NTLMChallenge m_challenge;
|
||||
|
||||
// User name, hashed password and algorithm type
|
||||
|
||||
private String m_username;
|
||||
private byte[] m_hashedPassword;
|
||||
private int m_hashType;
|
||||
|
||||
// Time that the authentication session will expire
|
||||
|
||||
private long m_authExpiresAt;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*/
|
||||
public NTLMPassthruToken()
|
||||
{
|
||||
// We do not know the username yet, and will not know the password
|
||||
|
||||
super("", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the challenge
|
||||
*
|
||||
* @return NTLMChallenge
|
||||
*/
|
||||
public final NTLMChallenge getChallenge()
|
||||
{
|
||||
return m_challenge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the user account
|
||||
*
|
||||
* @return Object
|
||||
*/
|
||||
public final Object getPrincipal()
|
||||
{
|
||||
return m_username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the hashed password
|
||||
*
|
||||
* @return byte[]
|
||||
*/
|
||||
public final byte[] getHashedPassword()
|
||||
{
|
||||
return m_hashedPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the hashed password type
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public final int getPasswordType()
|
||||
{
|
||||
return m_hashType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the authentication expiry time, this will be zero if the authentication session has not yet
|
||||
* been opened to the server
|
||||
*
|
||||
* @return long
|
||||
*/
|
||||
public final long getAuthenticationExpireTime()
|
||||
{
|
||||
return m_authExpiresAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the hashed password and type
|
||||
*
|
||||
* @param hashedPassword byte[]
|
||||
* @param hashType int
|
||||
*/
|
||||
public final void setUserAndPassword(String username, byte[] hashedPassword, int hashType)
|
||||
{
|
||||
m_username = username.toLowerCase();
|
||||
m_hashedPassword = hashedPassword;
|
||||
m_hashType = hashType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the challenge for this token
|
||||
*
|
||||
* @param challenge NTLMChallenge
|
||||
*/
|
||||
protected final void setChallenge(NTLMChallenge challenge)
|
||||
{
|
||||
m_challenge = challenge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the authentication expire time, this indicates that an authentication session is associated with this
|
||||
* token and the session will be closed if the authentication is not completed by this time.
|
||||
*
|
||||
* @param startTime long
|
||||
*/
|
||||
protected final void setAuthenticationExpireTime(long expireTime)
|
||||
{
|
||||
m_authExpiresAt = expireTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for object equality
|
||||
*
|
||||
* @param obj Object
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
// Only match on the same object
|
||||
|
||||
return this == obj;
|
||||
}
|
||||
}
|
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Alfresco Network License. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfrescosoftware.com/legal/
|
||||
*
|
||||
* Please view the license relevant to your network subscription.
|
||||
*
|
||||
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
|
||||
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
|
||||
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
|
||||
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
|
||||
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
|
||||
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
|
||||
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
|
||||
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
|
||||
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
|
||||
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
|
||||
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
|
||||
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
|
||||
*/
|
||||
package org.alfresco.repo.security.authentication.ntlm;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import net.sf.acegisecurity.UserDetails;
|
||||
import net.sf.acegisecurity.providers.dao.UsernameNotFoundException;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||
import org.alfresco.repo.security.authentication.MutableAuthenticationDao;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
/**
|
||||
* Null Mutable Authentication Dao Class
|
||||
*
|
||||
* <p>Mutable authentication implementation that does nothing.
|
||||
*
|
||||
* @author GKSpencer
|
||||
*/
|
||||
public class NullMutableAuthenticationDao implements MutableAuthenticationDao
|
||||
{
|
||||
/**
|
||||
* Method kept just for backward compatibility with older configurations that
|
||||
* might have been passing in a value.
|
||||
*
|
||||
* @param nodeService ignored
|
||||
*/
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a user with the given userName and password
|
||||
*
|
||||
* @param userName
|
||||
* @param rawPassword
|
||||
* @throws AuthenticationException
|
||||
*/
|
||||
public void createUser(String userName, char[] rawPassword) throws AuthenticationException
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Not implemented");
|
||||
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a user's password.
|
||||
*
|
||||
* @param userName
|
||||
* @param rawPassword
|
||||
* @throws AuthenticationException
|
||||
*/
|
||||
public void updateUser(String userName, char[] rawPassword) throws AuthenticationException
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Not implemented");
|
||||
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a user.
|
||||
*
|
||||
* @param userName
|
||||
* @throws AuthenticationException
|
||||
*/
|
||||
public void deleteUser(String userName) throws AuthenticationException
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Not implemented");
|
||||
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
/**
|
||||
* Check is a user exists.
|
||||
*
|
||||
* @param userName
|
||||
* @return
|
||||
*/
|
||||
public boolean userExists(String userName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable a user.
|
||||
*
|
||||
* @param userName
|
||||
* @param enabled
|
||||
*/
|
||||
public void setEnabled(String userName, boolean enabled)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Not implemented");
|
||||
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for user enabled
|
||||
*
|
||||
* @param userName
|
||||
* @return
|
||||
*/
|
||||
public boolean getEnabled(String userName)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Not implemented");
|
||||
|
||||
// return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if the account should expire
|
||||
*
|
||||
* @param userName
|
||||
* @param expires
|
||||
*/
|
||||
public void setAccountExpires(String userName, boolean expires)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Not implemented");
|
||||
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the account expire?
|
||||
*
|
||||
* @param userName
|
||||
* @return
|
||||
*/
|
||||
|
||||
public boolean getAccountExpires(String userName)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Not implemented");
|
||||
|
||||
// return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Has the account expired?
|
||||
*
|
||||
* @param userName
|
||||
* @return
|
||||
*/
|
||||
public boolean getAccountHasExpired(String userName)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Not implemented");
|
||||
|
||||
// return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if the password expires.
|
||||
*
|
||||
* @param userName
|
||||
* @param expires
|
||||
*/
|
||||
public void setCredentialsExpire(String userName, boolean expires)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Not implemented");
|
||||
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
/**
|
||||
* Do the credentials for the user expire?
|
||||
*
|
||||
* @param userName
|
||||
* @return
|
||||
*/
|
||||
public boolean getCredentialsExpire(String userName)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Not implemented");
|
||||
|
||||
// return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Have the credentials for the user expired?
|
||||
*
|
||||
* @param userName
|
||||
* @return
|
||||
*/
|
||||
public boolean getCredentialsHaveExpired(String userName)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Not implemented");
|
||||
|
||||
// return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if the account is locked.
|
||||
*
|
||||
* @param userName
|
||||
* @param locked
|
||||
*/
|
||||
public void setLocked(String userName, boolean locked)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Not implemented");
|
||||
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the account locked?
|
||||
*
|
||||
* @param userName
|
||||
* @return
|
||||
*/
|
||||
public boolean getAccountlocked(String userName)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Not implemented");
|
||||
|
||||
// return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the date on which the account expires
|
||||
*
|
||||
* @param userName
|
||||
* @param exipryDate
|
||||
*/
|
||||
public void setAccountExpiryDate(String userName, Date exipryDate)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Not implemented");
|
||||
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the date when this account expires.
|
||||
*
|
||||
* @param userName
|
||||
* @return
|
||||
*/
|
||||
public Date getAccountExpiryDate(String userName)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Not implemented");
|
||||
|
||||
// return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the date when credentials expire.
|
||||
*
|
||||
* @param userName
|
||||
* @param exipryDate
|
||||
*/
|
||||
public void setCredentialsExpiryDate(String userName, Date exipryDate)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Not implemented");
|
||||
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the date when the credentials/password expire.
|
||||
*
|
||||
* @param userName
|
||||
* @return
|
||||
*/
|
||||
public Date getCredentialsExpiryDate(String userName)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Not implemented");
|
||||
|
||||
// return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MD4 password hash
|
||||
*
|
||||
* @param userName
|
||||
* @return
|
||||
*/
|
||||
public String getMD4HashedPassword(String userName)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Not implemented");
|
||||
|
||||
// return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Are user names case sensitive?
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean getUserNamesAreCaseSensitive()
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Not implemented");
|
||||
|
||||
// return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the user details for the specified user
|
||||
*
|
||||
* @param user String
|
||||
* @return UserDetails
|
||||
* @exception UsernameNotFoundException
|
||||
* @exception DataAccessException
|
||||
*/
|
||||
public UserDetails loadUserByUsername(String arg0) throws UsernameNotFoundException, DataAccessException
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Not implemented");
|
||||
|
||||
// return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return salt for user
|
||||
*
|
||||
* @param user UserDetails
|
||||
* @return Object
|
||||
*/
|
||||
public Object getSalt(UserDetails user)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Not implemented");
|
||||
|
||||
// return null;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user