From d52a806a1df12d8fcee2b5c3af65ae4d77d52acc Mon Sep 17 00:00:00 2001 From: Luke Taylor Date: Sun, 13 Sep 2009 21:55:14 +0000 Subject: [PATCH] SEC-1233: Removed NTLM support for 3.0 --- ntlm/README | 5 - ntlm/applicationContext.xml | 95 ---- ntlm/pom.xml | 64 --- .../security/ui/ntlm/NtlmBaseException.java | 34 -- .../ui/ntlm/NtlmBeginHandshakeException.java | 29 - .../ui/ntlm/NtlmProcessingFilter.java | 520 ------------------ .../ntlm/NtlmProcessingFilterEntryPoint.java | 108 ---- .../ui/ntlm/NtlmType2MessageException.java | 48 -- ...lmUsernamePasswordAuthenticationToken.java | 59 -- .../NtlmAwareLdapAuthenticator.java | 108 ---- .../NtlmAwareLdapAuthenticatorTests.java | 50 -- ntlm/web.xml | 53 -- 12 files changed, 1173 deletions(-) delete mode 100755 ntlm/README delete mode 100755 ntlm/applicationContext.xml delete mode 100755 ntlm/pom.xml delete mode 100755 ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmBaseException.java delete mode 100755 ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmBeginHandshakeException.java delete mode 100755 ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmProcessingFilter.java delete mode 100755 ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmProcessingFilterEntryPoint.java delete mode 100755 ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmType2MessageException.java delete mode 100755 ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmUsernamePasswordAuthenticationToken.java delete mode 100755 ntlm/src/main/java/org/springframework/security/ui/ntlm/ldap/authenticator/NtlmAwareLdapAuthenticator.java delete mode 100644 ntlm/src/test/java/org/springframework/security/ui/ntlm/ldap/authenticator/NtlmAwareLdapAuthenticatorTests.java delete mode 100755 ntlm/web.xml diff --git a/ntlm/README b/ntlm/README deleted file mode 100755 index 5727d3ede1..0000000000 --- a/ntlm/README +++ /dev/null @@ -1,5 +0,0 @@ -Just place this folder into the SVN checkout of ACEGI sources. -Then modify the root pom.xml to include the folder as a module. - -The applicationContext.xml and web.xml files are included in -the root directory for example purposes only. \ No newline at end of file diff --git a/ntlm/applicationContext.xml b/ntlm/applicationContext.xml deleted file mode 100755 index ee6f35b59b..0000000000 --- a/ntlm/applicationContext.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - - CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON - PATTERN_TYPE_APACHE_ANT - /login_error.jsp=httpSessionContextIntegrationFilter - /**=httpSessionContextIntegrationFilter, exceptionTranslationFilter, ntlmFilter, filterSecurityInterceptor - - - - - - - - org.springframework.security.core.context.SecurityContextImpl - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - jdoe=PASSWORD,ROLE_USER - - - - - - - - - - CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON - PATTERN_TYPE_APACHE_ANT - /**=ROLE_USER - - - - - - - - false - - - - - - - - - - - - - - - - - - - - diff --git a/ntlm/pom.xml b/ntlm/pom.xml deleted file mode 100755 index 5043b786e5..0000000000 --- a/ntlm/pom.xml +++ /dev/null @@ -1,64 +0,0 @@ - - 4.0.0 - - org.springframework.security - spring-security-parent - 3.0.0.CI-SNAPSHOT - - jar - spring-security-ntlm - Spring Security - NTLM support - - - - org.springframework.security - spring-security-core - ${project.version} - - - org.springframework.security - spring-security-web - ${project.version} - - - org.springframework.security - spring-security-ldap - ${project.version} - - - - org.samba.jcifs - jcifs - 1.2.19 - - - javax.servlet - jsp-api - 2.0 - true - - - javax.servlet - servlet-api - - - org.springframework.ldap - spring-ldap-core - true - - - - - - - ${basedir}/src/main/resources - / - - **/* - - false - - - - - diff --git a/ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmBaseException.java b/ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmBaseException.java deleted file mode 100755 index a3d7613927..0000000000 --- a/ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmBaseException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright 2004-2007 Acegi Technology Pty Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.ui.ntlm; - -import org.springframework.security.core.AuthenticationException; - -/** - * Base class for NTLM exceptions so that it is easier to distinguish them - * from other AuthenticationExceptions in the - * {@link NtlmProcessingFilterEntryPoint}. Marked as abstract - * since this exception is never supposed to be instantiated. - * - * @author Edward Smith - */ -public abstract class NtlmBaseException extends AuthenticationException { - - public NtlmBaseException(final String msg) { - super(msg); - } - -} diff --git a/ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmBeginHandshakeException.java b/ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmBeginHandshakeException.java deleted file mode 100755 index 9d22d7a7da..0000000000 --- a/ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmBeginHandshakeException.java +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright 2004-2007 Acegi Technology Pty Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.ui.ntlm; - -/** - * Signals the beginning of an NTLM handshaking process. - * - * @author Edward Smith - */ -public class NtlmBeginHandshakeException extends NtlmBaseException { - - public NtlmBeginHandshakeException() { - super("NTLM"); - } - -} diff --git a/ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmProcessingFilter.java b/ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmProcessingFilter.java deleted file mode 100755 index 3f45676ae0..0000000000 --- a/ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmProcessingFilter.java +++ /dev/null @@ -1,520 +0,0 @@ -/* Copyright 2004-2007 Acegi Technology Pty Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.ui.ntlm; - -import java.io.IOException; -import java.net.UnknownHostException; -import java.util.Enumeration; -import java.util.Properties; - -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; - -import jcifs.Config; -import jcifs.UniAddress; -import jcifs.ntlmssp.Type1Message; -import jcifs.ntlmssp.Type2Message; -import jcifs.ntlmssp.Type3Message; -import jcifs.smb.NtlmChallenge; -import jcifs.smb.NtlmPasswordAuthentication; -import jcifs.smb.SmbAuthException; -import jcifs.smb.SmbException; -import jcifs.smb.SmbSession; -import jcifs.util.Base64; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.security.authentication.AnonymousAuthenticationToken; -import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; -import org.springframework.security.authentication.AuthenticationDetailsSource; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.authentication.InsufficientAuthenticationException; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationProcessingFilter; -import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; -import org.springframework.util.Assert; -import org.springframework.web.filter.GenericFilterBean; - -/** - * A clean-room implementation for Spring Security of an NTLM HTTP filter - * leveraging the JCIFS library. - *

- * NTLM is a Microsoft-developed protocol providing single sign-on capabilities - * to web applications and other integrated applications. It allows a web - * server to automatically discover the username of a browser client when that - * client is logged into a Windows domain and is using an NTLM-aware browser. - * A web application can then reuse the user's Windows credentials without - * having to ask for them again. - *

- * Because NTLM only provides the username of the Windows client, a Spring - * Security NTLM deployment must have a UserDetailsService that - * provides a UserDetails object with the empty string as the - * password and whatever GrantedAuthority values necessary to - * pass the FilterSecurityInterceptor. - *

- * The Spring Security bean configuration file must also place the - * ExceptionTranslationFilter before this filter in the - * FilterChainProxy definition. - * - * @author Davide Baroncelli - * @author Edward Smith - * @version $Id$ - */ -public class NtlmProcessingFilter extends GenericFilterBean { - //~ Static fields/initializers ===================================================================================== - - private static Log logger = LogFactory.getLog(NtlmProcessingFilter.class); - - private static final String STATE_ATTR = "SpringSecurityNtlm"; - private static final String CHALLENGE_ATTR = "NtlmChal"; - private static final Integer BEGIN = new Integer(0); - private static final Integer NEGOTIATE = new Integer(1); - private static final Integer COMPLETE = new Integer(2); - private static final Integer DELAYED = new Integer(3); - - //~ Instance fields ================================================================================================ - - /** Should the filter load balance among multiple domain controllers, default false */ - private boolean loadBalance; - - /** Should the domain name be stripped from the username, default true */ - private boolean stripDomain = true; - - /** Should the filter initiate NTLM negotiations, default true */ - private boolean forceIdentification = true; - - /** Should the filter retry NTLM on authorization failure, default false */ - private boolean retryOnAuthFailure; - - private String soTimeout; - private String cachePolicy; - private String defaultDomain; - private String domainController; - private AuthenticationManager authenticationManager; - private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource(); - - //~ Methods ======================================================================================================== - - /** - * Ensures an AuthenticationManager and authentication failure - * URL have been provided in the bean configuration file. - */ - @Override - public void afterPropertiesSet() { - Assert.notNull(this.authenticationManager, "An AuthenticationManager is required"); - - // Default to 5 minutes if not already specified - Config.setProperty("jcifs.smb.client.soTimeout", soTimeout == null ? "300000" : soTimeout); - // Default to 20 minutes if not already specified - Config.setProperty("jcifs.netbios.cachePolicy", cachePolicy == null ? "1200" : cachePolicy); - - if (domainController == null) { - domainController = defaultDomain; - } - } - - /** - * Sets the AuthenticationManager to use. - * - * @param authenticationManager the AuthenticationManager to use. - */ - public void setAuthenticationManager(AuthenticationManager authenticationManager) { - this.authenticationManager = authenticationManager; - } - - /** - * The NT domain against which clients should be authenticated. If the SMB - * client username and password are also set, then preauthentication will - * be used which is necessary to initialize the SMB signing digest. SMB - * signatures are required by default on Windows 2003 domain controllers. - * - * @param defaultDomain The name of the default domain. - */ - public void setDefaultDomain(String defaultDomain) { - this.defaultDomain = defaultDomain; - Config.setProperty("jcifs.smb.client.domain", defaultDomain); - } - - /** - * Sets the SMB client username. - * - * @param smbClientUsername The SMB client username. - */ - public void setSmbClientUsername(String smbClientUsername) { - Config.setProperty("jcifs.smb.client.username", smbClientUsername); - } - - /** - * Sets the SMB client password. - * - * @param smbClientPassword The SMB client password. - */ - public void setSmbClientPassword(String smbClientPassword) { - Config.setProperty("jcifs.smb.client.password", smbClientPassword); - } - - /** - * Sets the SMB client SSN limit. When set to 1, every - * authentication is forced to use a separate transport. This effectively - * ignores SMB signing requirements, however at the expense of reducing - * scalability. Preauthentication with a domain, username, and password is - * the preferred method for working with servers that require signatures. - * - * @param smbClientSSNLimit The SMB client SSN limit. - */ - public void setSmbClientSSNLimit(String smbClientSSNLimit) { - Config.setProperty("jcifs.smb.client.ssnLimit", smbClientSSNLimit); - } - - /** - * Configures JCIFS to use a WINS server. It is preferred to use a WINS - * server over a specific domain controller. Set this property instead of - * domainController if there is a WINS server available. - * - * @param netbiosWINS The WINS server JCIFS will use. - */ - public void setNetbiosWINS(String netbiosWINS) { - Config.setProperty("jcifs.netbios.wins", netbiosWINS); - } - - /** - * The IP address of any SMB server that should be used to authenticate - * HTTP clients. - * - * @param domainController The IP address of the domain controller. - */ - public void setDomainController(String domainController) { - this.domainController = domainController; - } - - /** - * If the default domain is specified and the domain controller is not - * specified, then query for domain controllers by name. When load - * balance is true, rotate through the list of domain - * controllers when authenticating users. - * - * @param loadBalance The load balance flag value. - */ - public void setLoadBalance(boolean loadBalance) { - this.loadBalance = loadBalance; - } - - /** - * Configures NtlmProcessingFilter to strip the Windows - * domain name from the username when set to true, which - * is the default value. - * - * @param stripDomain The strip domain flag value. - */ - public void setStripDomain(boolean stripDomain) { - this.stripDomain = stripDomain; - } - - /** - * Sets the jcifs.smb.client.soTimeout property to the - * timeout value specified in milliseconds. Defaults to 5 minutes - * if not specified. - * - * @param timeout The milliseconds timeout value. - */ - public void setSoTimeout(String timeout) { - this.soTimeout = timeout; - } - - /** - * Sets the jcifs.netbios.cachePolicy property to the - * number of seconds a NetBIOS address is cached by JCIFS. Defaults to - * 20 minutes if not specified. - * - * @param numSeconds The number of seconds a NetBIOS address is cached. - */ - public void setCachePolicy(String numSeconds) { - this.cachePolicy = numSeconds; - } - - /** - * Loads properties starting with "jcifs" into the JCIFS configuration. - * Any other properties are ignored. - * - * @param props The JCIFS properties to set. - */ - public void setJcifsProperties(Properties props) { - String name; - - for (Enumeration e=props.keys(); e.hasMoreElements();) { - name = (String) e.nextElement(); - if (name.startsWith("jcifs.")) { - Config.setProperty(name, props.getProperty(name)); - } - } - } - - /** - * Returns true if NTLM authentication is forced. - * - * @return true if NTLM authentication is forced. - */ - public boolean isForceIdentification() { - return this.forceIdentification; - } - - /** - * Sets a flag denoting whether NTLM authentication should be forced. - * - * @param forceIdentification the force identification flag value to set. - */ - public void setForceIdentification(boolean forceIdentification) { - this.forceIdentification = forceIdentification; - } - - /** - * Sets a flag denoting whether NTLM should retry whenever authentication - * fails. Retry will occur if the credentials are rejected by the domain controller or if an - * an {@link AuthenticationCredentialsNotFoundException} - * or {@link InsufficientAuthenticationException} is thrown. - * - * @param retryOnFailure the retry on failure flag value to set. - */ - public void setRetryOnAuthFailure(boolean retryOnFailure) { - this.retryOnAuthFailure = retryOnFailure; - } - - public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) { - Assert.notNull(authenticationDetailsSource, "authenticationDetailsSource cannot be null"); - this.authenticationDetailsSource = authenticationDetailsSource; - } - - public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) - throws IOException, ServletException { - HttpServletRequest request = (HttpServletRequest) req; - HttpServletResponse response = (HttpServletResponse) res; - final HttpSession session = request.getSession(); - Integer ntlmState = (Integer) session.getAttribute(STATE_ATTR); - - // Start NTLM negotiations the first time through the filter - if (ntlmState == null) { - if (forceIdentification) { - logger.debug("Starting NTLM handshake"); - session.setAttribute(STATE_ATTR, BEGIN); - throw new NtlmBeginHandshakeException(); - } else { - logger.debug("NTLM handshake not yet started"); - session.setAttribute(STATE_ATTR, DELAYED); - } - } - - // IE will send a Type 1 message to reauthenticate the user during an HTTP POST - if (ntlmState == COMPLETE && this.reAuthOnIEPost(request)) - ntlmState = BEGIN; - - final String authMessage = request.getHeader("Authorization"); - if (ntlmState != COMPLETE && authMessage != null && authMessage.startsWith("NTLM ")) { - final UniAddress dcAddress = this.getDCAddress(session); - if (ntlmState == BEGIN) { - logger.debug("Processing NTLM Type 1 Message"); - session.setAttribute(STATE_ATTR, NEGOTIATE); - this.processType1Message(authMessage, session, dcAddress); - } else { - logger.debug("Processing NTLM Type 3 Message"); - final NtlmPasswordAuthentication auth = this.processType3Message(authMessage, session, dcAddress); - logger.debug("NTLM negotiation complete"); - this.logon(session, dcAddress, auth); - session.setAttribute(STATE_ATTR, COMPLETE); - - // Do not reauthenticate the user in Spring Security during an IE POST - final Authentication myCurrentAuth = SecurityContextHolder.getContext().getAuthentication(); - if (myCurrentAuth == null || myCurrentAuth instanceof AnonymousAuthenticationToken) { - logger.debug("Authenticating user credentials"); - this.authenticate(request, response, session, auth); - } - } - } - - chain.doFilter(request, response); - } - - /** - * Returns true if reauthentication is needed on an IE POST. - */ - private boolean reAuthOnIEPost(final HttpServletRequest request) { - String ua = request.getHeader("User-Agent"); - return (request.getMethod().equalsIgnoreCase("POST") && ua != null && ua.indexOf("MSIE") != -1); - } - - /** - * Creates and returns a Type 2 message from the provided Type 1 message. - * - * @param message the Type 1 message to process. - * @param session the HTTPSession object. - * @param dcAddress the domain controller address. - * @throws IOException - */ - private void processType1Message(final String message, final HttpSession session, final UniAddress dcAddress) throws IOException { - final Type2Message type2msg = new Type2Message( - new Type1Message(Base64.decode(message.substring(5))), - this.getChallenge(session, dcAddress), - null); - throw new NtlmType2MessageException(Base64.encode(type2msg.toByteArray())); - } - - /** - * Builds and returns an NtlmPasswordAuthentication object - * from the provided Type 3 message. - * - * @param message the Type 3 message to process. - * @param session the HTTPSession object. - * @param dcAddress the domain controller address. - * @return an NtlmPasswordAuthentication object. - * @throws IOException - */ - private NtlmPasswordAuthentication processType3Message(final String message, final HttpSession session, final UniAddress dcAddress) throws IOException { - final Type3Message type3msg = new Type3Message(Base64.decode(message.substring(5))); - final byte[] lmResponse = (type3msg.getLMResponse() != null) ? type3msg.getLMResponse() : new byte[0]; - final byte[] ntResponse = (type3msg.getNTResponse() != null) ? type3msg.getNTResponse() : new byte[0]; - return new NtlmPasswordAuthentication( - type3msg.getDomain(), - type3msg.getUser(), - this.getChallenge(session, dcAddress), - lmResponse, - ntResponse); - } - - /** - * Checks the user credentials against the domain controller. - * - * @param session the HTTPSession object. - * @param dcAddress the domain controller address. - * @param auth the NtlmPasswordAuthentication object. - * @throws IOException - */ - private void logon(final HttpSession session, final UniAddress dcAddress, final NtlmPasswordAuthentication auth) throws IOException { - try { - SmbSession.logon(dcAddress, auth); - if (logger.isDebugEnabled()) { - logger.debug(auth + " successfully authenticated against " + dcAddress); - } - } catch(SmbAuthException e) { - logger.error("Credentials " + auth + " were not accepted by the domain controller " + dcAddress); - - if (retryOnAuthFailure) { - logger.debug("Restarting NTLM authentication handshake"); - session.setAttribute(STATE_ATTR, BEGIN); - throw new NtlmBeginHandshakeException(); - } - - throw new BadCredentialsException("Bad NTLM credentials"); - } finally { - session.removeAttribute(CHALLENGE_ATTR); - } - } - - /** - * Authenticates the user credentials acquired from NTLM against the Spring - * Security AuthenticationManager. - * - * @param request the HttpServletRequest object. - * @param response the HttpServletResponse object. - * @param session the HttpSession object. - * @param auth the NtlmPasswordAuthentication object. - * @throws IOException - */ - private void authenticate(final HttpServletRequest request, final HttpServletResponse response, final HttpSession session, final NtlmPasswordAuthentication auth) throws IOException { - final Authentication authResult; - final UsernamePasswordAuthenticationToken authRequest; - final Authentication backupAuth; - - authRequest = new NtlmUsernamePasswordAuthenticationToken(auth, stripDomain); - authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); - - // Place the last username attempted into HttpSession for views - session.setAttribute(UsernamePasswordAuthenticationProcessingFilter.SPRING_SECURITY_LAST_USERNAME_KEY, authRequest.getName()); - - // Backup the current authentication in case of an AuthenticationException - backupAuth = SecurityContextHolder.getContext().getAuthentication(); - - try { - // Authenitcate the user with the authentication manager - authResult = authenticationManager.authenticate(authRequest); - } catch (AuthenticationException failed) { - if (logger.isInfoEnabled()) { - logger.info("Authentication request for user: " + authRequest.getName() + " failed: " + failed.toString()); - } - - // Reset the backup Authentication object and rethrow the AuthenticationException - SecurityContextHolder.getContext().setAuthentication(backupAuth); - - if (retryOnAuthFailure && (failed instanceof AuthenticationCredentialsNotFoundException || failed instanceof InsufficientAuthenticationException)) { - logger.debug("Restart NTLM authentication handshake due to AuthenticationException"); - session.setAttribute(STATE_ATTR, BEGIN); - throw new NtlmBeginHandshakeException(); - } - - throw failed; - } - - // Set the Authentication object with the valid authentication result - SecurityContextHolder.getContext().setAuthentication(authResult); - } - - /** - * Returns the domain controller address based on the loadBalance - * setting. - * - * @param session the HttpSession object. - * @return the domain controller address. - * @throws UnknownHostException - * @throws SmbException - */ - private UniAddress getDCAddress(final HttpSession session) throws UnknownHostException, SmbException { - if (loadBalance) { - NtlmChallenge chal = (NtlmChallenge) session.getAttribute(CHALLENGE_ATTR); - if (chal == null) { - chal = SmbSession.getChallengeForDomain(); - session.setAttribute(CHALLENGE_ATTR, chal); - } - return chal.dc; - } - - return UniAddress.getByName(domainController, true); - } - - /** - * Returns the domain controller challenge based on the loadBalance - * setting. - * - * @param session the HttpSession object. - * @param dcAddress the domain controller address. - * @return the domain controller challenge. - * @throws UnknownHostException - * @throws SmbException - */ - private byte[] getChallenge(final HttpSession session, final UniAddress dcAddress) throws UnknownHostException, SmbException { - if (loadBalance) { - return ((NtlmChallenge) session.getAttribute(CHALLENGE_ATTR)).challenge; - } - - return SmbSession.getChallenge(dcAddress); - } -} diff --git a/ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmProcessingFilterEntryPoint.java b/ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmProcessingFilterEntryPoint.java deleted file mode 100755 index f755f1b67e..0000000000 --- a/ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmProcessingFilterEntryPoint.java +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright 2004-2007 Acegi Technology Pty Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.ui.ntlm; - -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.AuthenticationEntryPoint; -import org.springframework.util.Assert; - -/** - * Used by ExceptionTranslationFilter to assist with the NTLM - * negotiation. Also handles redirecting the user to the authentication - * failure URL if an {@link AuthenticationException} that is not a subclass of - * {@link NtlmBaseException} is received. - * - * @author Davide Baroncelli - * @author Edward Smith - * @version $Id$ - */ -public class NtlmProcessingFilterEntryPoint implements AuthenticationEntryPoint { - - //~ Instance fields ================================================================================================ - - /** Where to redirect the browser to if authentication fails */ - private String authenticationFailureUrl; - - //~ Methods ======================================================================================================== - - /** - * Sets the authentication failure URL. - * - * @param authenticationFailureUrl the authentication failure URL. - */ - public void setAuthenticationFailureUrl(String authenticationFailureUrl) { - Assert.hasLength(authenticationFailureUrl, "authenticationFailureUrl must be specified"); - this.authenticationFailureUrl = authenticationFailureUrl; - } - - /** - * Sends an NTLM challenge to the browser requiring authentication. The - * WWW-Authenticate header is populated with the appropriate information - * during the negotiation lifecycle by calling the getMessage() method - * from an NTLM-specific subclass of {@link NtlmBaseException}: - *

- *

- * - * If the {@link AuthenticationException} is not a subclass of - * {@link NtlmBaseException}, then redirect the user to the authentication - * failure URL. - * - * @param request The {@link HttpServletRequest} object. - * @param response Then {@link HttpServletResponse} object. - * @param authException Either {@link NtlmBeginHandshakeException}, - * {@link NtlmType2MessageException}, or - * {@link AuthenticationException} - */ - public void commence(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException authException) throws IOException, ServletException { - final HttpServletResponse resp = (HttpServletResponse) response; - - if (authException instanceof NtlmBaseException) { - if (authException instanceof NtlmType2MessageException) { - ((NtlmType2MessageException) authException).preserveAuthentication(); - } - resp.setHeader("WWW-Authenticate", authException.getMessage()); - resp.setHeader("Connection", "Keep-Alive"); - resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED); - resp.setContentLength(0); - resp.flushBuffer(); - - return; - } - - if (authenticationFailureUrl == null) { - if (!response.isCommitted()) { - ((HttpServletResponse) response).sendError(HttpServletResponse.SC_FORBIDDEN, authException.getMessage()); - } - } else { - String url = authenticationFailureUrl; - if (!url.startsWith("http://") && !url.startsWith("https://")) { - url = ((HttpServletRequest) request).getContextPath() + url; - } - - resp.sendRedirect(resp.encodeRedirectURL(url)); - } - } - -} diff --git a/ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmType2MessageException.java b/ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmType2MessageException.java deleted file mode 100755 index de1277ca07..0000000000 --- a/ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmType2MessageException.java +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright 2004-2007 Acegi Technology Pty Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.ui.ntlm; - -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; - -/** - * Contains the NTLM Type 2 message that is sent back to the client during - * negotiations. - * - * @author Edward Smith - */ -public class NtlmType2MessageException extends NtlmBaseException { - - private static final long serialVersionUID = 1L; - - private final Authentication auth; - - public NtlmType2MessageException(final String type2Msg) { - super("NTLM " + type2Msg); - auth = SecurityContextHolder.getContext().getAuthentication(); - } - - /** - * Preserve the existing Authentication object each time - * Internet Explorer does a POST. - */ - public void preserveAuthentication() { - if (auth != null) { - SecurityContextHolder.getContext().setAuthentication(auth); - } - } - -} diff --git a/ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmUsernamePasswordAuthenticationToken.java b/ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmUsernamePasswordAuthenticationToken.java deleted file mode 100755 index 142a0488e8..0000000000 --- a/ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmUsernamePasswordAuthenticationToken.java +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright 2004-2007 Acegi Technology Pty Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.ui.ntlm; - -import java.util.List; - -import jcifs.smb.NtlmPasswordAuthentication; - -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.AuthorityUtils; - -/** - * An NTLM-specific {@link UsernamePasswordAuthenticationToken} that allows any provider to bypass the problem of an - * empty password since NTLM does not retrieve the user's password from the PDC. - * - * @author Sylvain Mougenot - */ -public class NtlmUsernamePasswordAuthenticationToken extends UsernamePasswordAuthenticationToken { - - private static final long serialVersionUID = 1L; - - /** - * Dummy authority array which is passed to the constructor of the parent class, - * ensuring that the "authenticated" property is set to "true" by default. See SEC-609. - */ - private static final List NTLM_AUTHENTICATED = - AuthorityUtils.createAuthorityList("NTLM_AUTHENTICATED"); - - /** - * Spring Security often checks password ; but we do not have one. This is the replacement password - */ - public static final String DEFAULT_PASSWORD = ""; - - /** - * Create an NTLM {@link UsernamePasswordAuthenticationToken} using the - * JCIFS {@link NtlmPasswordAuthentication} object. - * - * @param ntlmAuth The {@link NtlmPasswordAuthentication} object. - * @param stripDomain Uses just the username if true, - * otherwise use the username and domain name. - */ - public NtlmUsernamePasswordAuthenticationToken(NtlmPasswordAuthentication ntlmAuth, boolean stripDomain) { - super((stripDomain) ? ntlmAuth.getUsername() : ntlmAuth.getName(), DEFAULT_PASSWORD, NTLM_AUTHENTICATED); - } -} diff --git a/ntlm/src/main/java/org/springframework/security/ui/ntlm/ldap/authenticator/NtlmAwareLdapAuthenticator.java b/ntlm/src/main/java/org/springframework/security/ui/ntlm/ldap/authenticator/NtlmAwareLdapAuthenticator.java deleted file mode 100755 index 960d700ace..0000000000 --- a/ntlm/src/main/java/org/springframework/security/ui/ntlm/ldap/authenticator/NtlmAwareLdapAuthenticator.java +++ /dev/null @@ -1,108 +0,0 @@ -/** - * - */ -package org.springframework.security.ui.ntlm.ldap.authenticator; - -import java.util.Iterator; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.ldap.NameNotFoundException; -import org.springframework.ldap.core.DirContextOperations; -import org.springframework.ldap.core.support.BaseLdapPathContextSource; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.core.Authentication; -import org.springframework.security.ldap.SpringSecurityLdapTemplate; -import org.springframework.security.ldap.authentication.BindAuthenticator; -import org.springframework.security.ui.ntlm.NtlmUsernamePasswordAuthenticationToken; - -/** - * Loads the UserDetails if authentication was already performed by NTLM (indicated by the type of authentication - * token submitted). Otherwise falls back to the parent class behaviour, attempting to bind as the user. - * - * @author sylvain.mougenot - * - */ -public class NtlmAwareLdapAuthenticator extends BindAuthenticator { - //~ Static fields/initializers ===================================================================================== - - private static final Log logger = LogFactory.getLog(NtlmAwareLdapAuthenticator.class); - - - //~ Constructors =================================================================================================== - - public NtlmAwareLdapAuthenticator(BaseLdapPathContextSource contextSource) { - super(contextSource); - } - - //~ Methods ======================================================================================================== - - /** - * Loads the user context information without binding. - */ - protected DirContextOperations loadUser(String aUserDn, String aUserName) { - SpringSecurityLdapTemplate template = new SpringSecurityLdapTemplate(getContextSource()); - - try { - DirContextOperations user = template.retrieveEntry(aUserDn, getUserAttributes()); - - return user; - } catch (NameNotFoundException e) { - // This will be thrown if an invalid user name is used and the method may - // be called multiple times to try different names, so we trap the exception. - if (logger.isDebugEnabled()) { - logger.debug("Failed to load user " + aUserDn + ": " + e.getMessage(), e); - } - } - return null; - } - - /** - * If the supplied Authentication object is of type NtlmUsernamePasswordAuthenticationToken, - * the information stored in the user's directory entry is loaded without attempting to authenticate them. - * Otherwise the parent class is called to perform a bind operation to authenticate the user. - */ - public DirContextOperations authenticate(Authentication authentication) { - if (!(authentication instanceof NtlmUsernamePasswordAuthenticationToken)) { - // Not NTLM authenticated, so call the base class to authenticate the user. - return super.authenticate(authentication); - } - - if (!authentication.isAuthenticated()) { - throw new BadCredentialsException("Unauthenticated NTLM authentication token found"); - } - - if (logger.isDebugEnabled()) { - logger.debug("authenticate(NtlmUsernamePasswordAuthenticationToken) - start"); //$NON-NLS-1$ - } - - final String userName = authentication.getName(); - DirContextOperations user = null; - - // If DN patterns are configured, try authenticating with them directly - Iterator myDns = getUserDns(userName).iterator(); - - // tries them all until we found something - while (myDns.hasNext() && (user == null)) { - user = loadUser((String) myDns.next(), userName); - } - - // Otherwise use the configured locator to find the user - // and authenticate with the returned DN. - if ((user == null) && (getUserSearch() != null)) { - DirContextOperations userFromSearch = getUserSearch().searchForUser(userName); - // lancer l'identificvation - user = loadUser(userFromSearch.getDn().toString(), userName); - } - - // Failed to locate the user in the LDAP directory - if (user == null) { - throw new BadCredentialsException(messages.getMessage("BindAuthenticator.badCredentials", "Bad credentials")); - } - - if (logger.isDebugEnabled()) { - logger.debug("authenticate(NtlmUsernamePasswordAuthenticationToken) - end"); //$NON-NLS-1$ - } - return user; - } -} diff --git a/ntlm/src/test/java/org/springframework/security/ui/ntlm/ldap/authenticator/NtlmAwareLdapAuthenticatorTests.java b/ntlm/src/test/java/org/springframework/security/ui/ntlm/ldap/authenticator/NtlmAwareLdapAuthenticatorTests.java deleted file mode 100644 index 2e79b45381..0000000000 --- a/ntlm/src/test/java/org/springframework/security/ui/ntlm/ldap/authenticator/NtlmAwareLdapAuthenticatorTests.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.springframework.security.ui.ntlm.ldap.authenticator; - -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.ldap.DefaultSpringSecurityContextSource; -import org.springframework.security.ui.ntlm.NtlmUsernamePasswordAuthenticationToken; -import org.springframework.ldap.core.DirContextAdapter; -import org.springframework.ldap.core.DirContextOperations; - -import jcifs.smb.NtlmPasswordAuthentication; -import org.junit.Test; - -/** - * @author Luke Taylor - * @version $Id$ - */ -public class NtlmAwareLdapAuthenticatorTests { - /** - * See SEC-609. - */ - @Test(expected = BadCredentialsException.class) - public void unauthenticatedTokenIsRejected() { - NtlmAwareLdapAuthenticator authenticator = new NtlmAwareLdapAuthenticator( - new DefaultSpringSecurityContextSource("ldap://blah")); - - NtlmUsernamePasswordAuthenticationToken token = new NtlmUsernamePasswordAuthenticationToken( - new NtlmPasswordAuthentication("blah"), false); - token.setAuthenticated(false); - - authenticator.authenticate(token); - } - - @Test - public void authenticatedTokenIsAccepted() { - NtlmAwareLdapAuthenticator authenticator = new NtlmAwareLdapAuthenticator(new DefaultSpringSecurityContextSource("ldap://blah")) { - // mimic loading of user - protected DirContextOperations loadUser(String aUserDn, String aUserName) { - return new DirContextAdapter(); - } - }; - - authenticator.setUserDnPatterns(new String[] {"somepattern"}); - - NtlmUsernamePasswordAuthenticationToken token = new NtlmUsernamePasswordAuthenticationToken( - new NtlmPasswordAuthentication("blah"), false); - - authenticator.authenticate(token); - } - - -} diff --git a/ntlm/web.xml b/ntlm/web.xml deleted file mode 100755 index f0c71db7e8..0000000000 --- a/ntlm/web.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - Spring Security NTLM - - - - - - contextConfigLocation - /WEB-INF/applicationContext.xml - - - - log4jConfigLocation - /WEB-INF/log4j.properties - - - - - filterChainProxy - org.springframework.web.filter.DelegatingFilterProxy - - - - filterChainProxy - /* - - - - - - org.springframework.web.context.ContextLoaderListener - - - - - org.springframework.web.util.Log4jConfigListener - - - - - org.springframework.security.ui.session.HttpSessionEventPublisher - - - - index.html - index.htm - index.jsp - default.html - default.htm - default.jsp - -