mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
Align Alfresco, CIFS and FTP authentication stacks for NTLM passthru, kerberos and LDAP
- PassthruServerFactory created to allows PassthruServers singleton to be shared by CIFS, FTP and Alfresco passthru authenticators - Also added NTLM + Alfresco (non-passthru) example. Doesn't seem to work yet! - ExtendedServerConfigurationAccessor interface added BaseSSOAuthenticationFilter to get at local server name info from file server configuration - toString() added to CIFSAuthenticator so that we can still properly log the authenticator type - Fixed WebDAVServlet to go through ServerConfigurationAccessor interface to avoid ClassCastException git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@13823 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -36,6 +36,7 @@ import javax.servlet.http.HttpServletResponse;
|
|||||||
import javax.transaction.UserTransaction;
|
import javax.transaction.UserTransaction;
|
||||||
|
|
||||||
import org.alfresco.filesys.ServerConfigurationBean;
|
import org.alfresco.filesys.ServerConfigurationBean;
|
||||||
|
import org.alfresco.jlan.server.config.ServerConfigurationAccessor;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationContext;
|
import org.alfresco.repo.security.authentication.AuthenticationContext;
|
||||||
import org.alfresco.repo.tenant.TenantService;
|
import org.alfresco.repo.tenant.TenantService;
|
||||||
import org.alfresco.service.ServiceRegistry;
|
import org.alfresco.service.ServiceRegistry;
|
||||||
@@ -333,7 +334,7 @@ public class WebDAVServlet extends HttpServlet
|
|||||||
|
|
||||||
// Initialize the root node
|
// Initialize the root node
|
||||||
|
|
||||||
ServerConfigurationBean fileSrvConfig = (ServerConfigurationBean) context.getBean(ServerConfigurationBean.SERVER_CONFIGURATION);
|
ServerConfigurationAccessor fileSrvConfig = (ServerConfigurationAccessor) context.getBean(ServerConfigurationBean.SERVER_CONFIGURATION);
|
||||||
if ( fileSrvConfig == null)
|
if ( fileSrvConfig == null)
|
||||||
throw new ServletException("File server configuration not available");
|
throw new ServletException("File server configuration not available");
|
||||||
|
|
||||||
|
@@ -425,10 +425,11 @@ public abstract class BaseNTLMAuthenticationFilter extends BaseSSOAuthentication
|
|||||||
|
|
||||||
// Build a type2 message to send back to the client, containing the challenge
|
// Build a type2 message to send back to the client, containing the challenge
|
||||||
List<TargetInfo> tList = new ArrayList<TargetInfo>();
|
List<TargetInfo> tList = new ArrayList<TargetInfo>();
|
||||||
tList.add(new TargetInfo(NTLM.TargetServer, m_srvName));
|
String srvName = getServerName();
|
||||||
|
tList.add(new TargetInfo(NTLM.TargetServer, srvName));
|
||||||
|
|
||||||
Type2NTLMMessage type2Msg = new Type2NTLMMessage();
|
Type2NTLMMessage type2Msg = new Type2NTLMMessage();
|
||||||
type2Msg.buildType2(ntlmFlags, m_srvName, challenge, null, tList);
|
type2Msg.buildType2(ntlmFlags, srvName, challenge, null, tList);
|
||||||
|
|
||||||
// Store the NTLM logon details, cache the type2 message, and token if using passthru
|
// Store the NTLM logon details, cache the type2 message, and token if using passthru
|
||||||
ntlmDetails = new NTLMLogonDetails();
|
ntlmDetails = new NTLMLogonDetails();
|
||||||
@@ -652,10 +653,11 @@ public abstract class BaseNTLMAuthenticationFilter extends BaseSSOAuthentication
|
|||||||
onValidate(req, session);
|
onValidate(req, session);
|
||||||
|
|
||||||
// Update the NTLM logon details in the session
|
// Update the NTLM logon details in the session
|
||||||
|
String srvName = getServerName();
|
||||||
if (ntlmDetails == null)
|
if (ntlmDetails == null)
|
||||||
{
|
{
|
||||||
// No cached NTLM details
|
// No cached NTLM details
|
||||||
ntlmDetails = new NTLMLogonDetails(userName, workstation, domain, false, m_srvName);
|
ntlmDetails = new NTLMLogonDetails(userName, workstation, domain, false, srvName);
|
||||||
ntlmDetails.setNTLMHashedPassword(type3Msg.getNTLMHash());
|
ntlmDetails.setNTLMHashedPassword(type3Msg.getNTLMHash());
|
||||||
session.setAttribute(NTLM_AUTH_DETAILS, ntlmDetails);
|
session.setAttribute(NTLM_AUTH_DETAILS, ntlmDetails);
|
||||||
|
|
||||||
@@ -665,7 +667,7 @@ public abstract class BaseNTLMAuthenticationFilter extends BaseSSOAuthentication
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Update the cached NTLM details
|
// Update the cached NTLM details
|
||||||
ntlmDetails.setDetails(userName, workstation, domain, false, m_srvName);
|
ntlmDetails.setDetails(userName, workstation, domain, false, srvName);
|
||||||
ntlmDetails.setNTLMHashedPassword(type3Msg.getNTLMHash());
|
ntlmDetails.setNTLMHashedPassword(type3Msg.getNTLMHash());
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
|
@@ -34,7 +34,8 @@ import javax.servlet.http.HttpServletResponse;
|
|||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
import javax.transaction.UserTransaction;
|
import javax.transaction.UserTransaction;
|
||||||
|
|
||||||
import org.alfresco.filesys.ServerConfigurationBean;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
import org.alfresco.filesys.ExtendedServerConfigurationAccessor;
|
||||||
import org.alfresco.jlan.server.auth.ntlm.NTLM;
|
import org.alfresco.jlan.server.auth.ntlm.NTLM;
|
||||||
import org.alfresco.jlan.server.auth.passthru.DomainMapping;
|
import org.alfresco.jlan.server.auth.passthru.DomainMapping;
|
||||||
import org.alfresco.jlan.server.config.SecurityConfigSection;
|
import org.alfresco.jlan.server.config.SecurityConfigSection;
|
||||||
@@ -87,11 +88,7 @@ public abstract class BaseSSOAuthenticationFilter implements DependencyInjectedF
|
|||||||
|
|
||||||
// File server configuration
|
// File server configuration
|
||||||
|
|
||||||
private ServerConfigurationBean serverConfigurationBean;
|
private ExtendedServerConfigurationAccessor serverConfiguration;
|
||||||
|
|
||||||
// Security configuration section, for domain mappings
|
|
||||||
|
|
||||||
private SecurityConfigSection securityConfigSection;
|
|
||||||
|
|
||||||
// Various services required by NTLM authenticator
|
// Various services required by NTLM authenticator
|
||||||
|
|
||||||
@@ -101,10 +98,6 @@ public abstract class BaseSSOAuthenticationFilter implements DependencyInjectedF
|
|||||||
protected NodeService nodeService;
|
protected NodeService nodeService;
|
||||||
protected TransactionService transactionService;
|
protected TransactionService transactionService;
|
||||||
|
|
||||||
// Local server name, from either the file servers config or DNS host name
|
|
||||||
|
|
||||||
protected String m_srvName;
|
|
||||||
|
|
||||||
// Login page relative address, if null then login will loop until a valid login is received
|
// Login page relative address, if null then login will loop until a valid login is received
|
||||||
|
|
||||||
private String m_loginPage;
|
private String m_loginPage;
|
||||||
@@ -116,13 +109,16 @@ public abstract class BaseSSOAuthenticationFilter implements DependencyInjectedF
|
|||||||
// User object attribute name
|
// User object attribute name
|
||||||
|
|
||||||
private String m_userAttributeName = AUTHENTICATION_USER;
|
private String m_userAttributeName = AUTHENTICATION_USER;
|
||||||
|
|
||||||
|
private String m_lastConfiguredServerName;
|
||||||
|
private String m_lastResolvedServerName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param serverConfigurationBean the serverConfigurationBean to set
|
* @param serverConfiguration the serverConfiguration to set
|
||||||
*/
|
*/
|
||||||
public void setServerConfigurationBean(ServerConfigurationBean serverConfigurationBean)
|
public void setServerConfiguration(ExtendedServerConfigurationAccessor serverConfiguration)
|
||||||
{
|
{
|
||||||
this.serverConfigurationBean = serverConfigurationBean;
|
this.serverConfiguration = serverConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -163,93 +159,13 @@ public abstract class BaseSSOAuthenticationFilter implements DependencyInjectedF
|
|||||||
public void setTransactionService(TransactionService transactionService)
|
public void setTransactionService(TransactionService transactionService)
|
||||||
{
|
{
|
||||||
this.transactionService = transactionService;
|
this.transactionService = transactionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||||
*/
|
*/
|
||||||
public void afterPropertiesSet() throws Exception
|
public void afterPropertiesSet() throws Exception
|
||||||
{
|
{
|
||||||
// Get the local server name, try the file server config first
|
|
||||||
if (serverConfigurationBean != null)
|
|
||||||
{
|
|
||||||
m_srvName = serverConfigurationBean.getServerName();
|
|
||||||
if ( m_srvName.length() == 0)
|
|
||||||
m_srvName = null;
|
|
||||||
|
|
||||||
if (m_srvName != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
InetAddress resolved = InetAddress.getByName(m_srvName);
|
|
||||||
if (resolved == null)
|
|
||||||
{
|
|
||||||
// Failed to resolve the configured name
|
|
||||||
|
|
||||||
m_srvName = serverConfigurationBean.getLocalServerName(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (UnknownHostException ex)
|
|
||||||
{
|
|
||||||
if (getLogger().isWarnEnabled())
|
|
||||||
getLogger().warn("NTLM filter, error resolving CIFS host name" + m_srvName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we still do not have a name use the DNS name of the server, with the domain part removed
|
|
||||||
|
|
||||||
if ( m_srvName == null)
|
|
||||||
{
|
|
||||||
m_srvName = serverConfigurationBean.getLocalServerName(true);
|
|
||||||
|
|
||||||
// DEBUG
|
|
||||||
|
|
||||||
if ( getLogger().isInfoEnabled())
|
|
||||||
getLogger().info("NTLM filter using server name " + m_srvName);
|
|
||||||
|
|
||||||
// DEBUG
|
|
||||||
|
|
||||||
if ( getLogger().isInfoEnabled())
|
|
||||||
getLogger().info("NTLM filter using server name " + m_srvName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the security configuration section
|
|
||||||
|
|
||||||
securityConfigSection = (SecurityConfigSection)serverConfigurationBean.getConfigSection(SecurityConfigSection.SectionName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Get the host name
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Get the local host name
|
|
||||||
|
|
||||||
m_srvName = InetAddress.getLocalHost().getHostName();
|
|
||||||
|
|
||||||
// Strip any domain name
|
|
||||||
|
|
||||||
int pos = m_srvName.indexOf(".");
|
|
||||||
if (pos != -1)
|
|
||||||
{
|
|
||||||
m_srvName = m_srvName.substring(0, pos - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (UnknownHostException ex)
|
|
||||||
{
|
|
||||||
if (getLogger().isErrorEnabled())
|
|
||||||
getLogger().error("NTLM filter, error getting local host name", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the server name is valid
|
|
||||||
|
|
||||||
if (m_srvName == null || m_srvName.length() == 0)
|
|
||||||
{
|
|
||||||
throw new ServletException("Failed to get local server name");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -426,7 +342,7 @@ public abstract class BaseSSOAuthenticationFilter implements DependencyInjectedF
|
|||||||
protected final String mapClientAddressToDomain(String clientIP)
|
protected final String mapClientAddressToDomain(String clientIP)
|
||||||
{
|
{
|
||||||
// Check if there are any domain mappings
|
// Check if there are any domain mappings
|
||||||
|
SecurityConfigSection securityConfigSection = getSecurityConfigSection();
|
||||||
if (securityConfigSection != null && securityConfigSection.hasDomainMappings() == false)
|
if (securityConfigSection != null && securityConfigSection.hasDomainMappings() == false)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@@ -639,5 +555,109 @@ public abstract class BaseSSOAuthenticationFilter implements DependencyInjectedF
|
|||||||
}
|
}
|
||||||
|
|
||||||
return isNTLMSSP;
|
return isNTLMSSP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Because the file server configuration may change during the lifetime of this filter, this method checks against
|
||||||
|
* the last configured server name before returning a cached result
|
||||||
|
*
|
||||||
|
* @return resolved local server name
|
||||||
|
*/
|
||||||
|
protected synchronized String getServerName()
|
||||||
|
{
|
||||||
|
// Get the local server name, try the file server config first
|
||||||
|
String srvName = null;
|
||||||
|
if (serverConfiguration != null)
|
||||||
|
{
|
||||||
|
srvName = serverConfiguration.getServerName();
|
||||||
|
if (srvName != null && srvName.length() == 0)
|
||||||
|
{
|
||||||
|
srvName = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_lastResolvedServerName != null
|
||||||
|
&& (m_lastConfiguredServerName == null && srvName == null || m_lastConfiguredServerName.equals(srvName)))
|
||||||
|
{
|
||||||
|
return m_lastResolvedServerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lastResolvedServerName = null;
|
||||||
|
m_lastConfiguredServerName = srvName;
|
||||||
|
if (serverConfiguration != null)
|
||||||
|
{
|
||||||
|
if (m_lastConfiguredServerName != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
InetAddress resolved = InetAddress.getByName(m_lastConfiguredServerName);
|
||||||
|
if (resolved == null)
|
||||||
|
{
|
||||||
|
// Failed to resolve the configured name
|
||||||
|
|
||||||
|
m_lastResolvedServerName = serverConfiguration.getLocalServerName(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_lastResolvedServerName = m_lastConfiguredServerName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (UnknownHostException ex)
|
||||||
|
{
|
||||||
|
if (getLogger().isWarnEnabled())
|
||||||
|
getLogger().warn("NTLM filter, error resolving CIFS host name" + m_lastConfiguredServerName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we still do not have a name use the DNS name of the server, with the domain part removed
|
||||||
|
|
||||||
|
if (m_lastResolvedServerName == null)
|
||||||
|
{
|
||||||
|
m_lastResolvedServerName = serverConfiguration.getLocalServerName(true);
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
|
||||||
|
if (getLogger().isInfoEnabled())
|
||||||
|
getLogger().info("NTLM filter using server name " + m_lastResolvedServerName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Get the host name
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Get the local host name
|
||||||
|
|
||||||
|
m_lastResolvedServerName = InetAddress.getLocalHost().getHostName();
|
||||||
|
|
||||||
|
// Strip any domain name
|
||||||
|
|
||||||
|
int pos = m_lastResolvedServerName.indexOf(".");
|
||||||
|
if (pos != -1)
|
||||||
|
{
|
||||||
|
m_lastResolvedServerName = m_lastResolvedServerName.substring(0, pos - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (UnknownHostException ex)
|
||||||
|
{
|
||||||
|
if (getLogger().isErrorEnabled())
|
||||||
|
getLogger().error("NTLM filter, error getting local host name", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the server name is valid
|
||||||
|
|
||||||
|
if (m_lastResolvedServerName == null || m_lastResolvedServerName.length() == 0)
|
||||||
|
{
|
||||||
|
throw new AlfrescoRuntimeException("Failed to get local server name");
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_lastResolvedServerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SecurityConfigSection getSecurityConfigSection()
|
||||||
|
{
|
||||||
|
return serverConfiguration == null ? null : (SecurityConfigSection) serverConfiguration.getConfigSection(SecurityConfigSection.SectionName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user