浏览代码

SEC-1233: Removed NTLM support for 3.0

Luke Taylor 16 年之前
父节点
当前提交
d52a806a1d

+ 0 - 5
ntlm/README

@@ -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.

+ 0 - 95
ntlm/applicationContext.xml

@@ -1,95 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
-
-<beans>
-
-    <bean id="filterChainProxy" class="org.springframework.security.util.FilterChainProxy">
-        <property name="filterInvocationDefinitionSource">
-            <value>
-            CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
-            PATTERN_TYPE_APACHE_ANT
-            /login_error.jsp=httpSessionContextIntegrationFilter
-            /**=httpSessionContextIntegrationFilter, exceptionTranslationFilter, ntlmFilter, filterSecurityInterceptor
-            </value>
-        </property>
-    </bean>
-
-    <!-- The first item in the Chain: httpSessionContextIntegrationFilter -->
-    <bean id="httpSessionContextIntegrationFilter" class="org.springframework.security.core.context.HttpSessionContextIntegrationFilter">
-        <property name="context">
-            <value>org.springframework.security.core.context.SecurityContextImpl</value>
-        </property>
-    </bean>
-
-    <!-- the second item in the chain: exceptionTranslationFilter -->
-    <bean id="exceptionTranslationFilter" class="org.springframework.security.ui.ExceptionTranslationFilter">
-        <property name="authenticationEntryPoint" ref="ntlmEntryPoint"/>
-    </bean>
-
-    <!-- the third item in the chain: ntlmFilter -->
-    <bean id="ntlmFilter" class="org.springframework.security.ui.ntlm.NtlmProcessingFilter">
-        <property name="defaultDomain" value="YOURDOMAIN"/>
-        <!-- It is better to use a WINS server if available over a specific domain controller
-         <property name="domainController" value="FOO"/> -->
-        <property name="netbiosWINS" value="192.168.0.3"/>
-        <property name="authenticationManager" ref="providerManager"/>
-    </bean>
-
-    <bean id="providerManager" class="org.springframework.security.authentication.ProviderManager">
-        <property name="providers">
-            <list>
-                <ref local="daoAuthenticationProvider"/>
-            </list>
-        </property>
-    </bean>
-
-    <bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
-        <property name="userDetailsService">
-            <ref local="memoryUserDetailsService"/>
-        </property>
-    </bean>
-
-    <!-- NOTE: You will need to write a custom UserDetailsService in most cases -->
-    <bean id="memoryUserDetailsService" class="org.springframework.security.core.userdetails.memory.InMemoryDaoImpl">
-        <property name="userMap">
-            <value>jdoe=PASSWORD,ROLE_USER</value>
-        </property>
-    </bean>
-
-    <!-- the fourth item in the chain: filterSecurityInterceptor -->
-    <bean id="filterSecurityInterceptor" class="org.springframework.security.access.intercept.web.FilterSecurityInterceptor">
-        <property name="authenticationManager"><ref local="providerManager"/></property>
-        <property name="accessDecisionManager"><ref local="accessDecisionManager"/></property>
-        <property name="securityMetadataSource">
-            <value>
-            CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
-            PATTERN_TYPE_APACHE_ANT
-            /**=ROLE_USER
-            </value>
-        </property>
-    </bean>
-
-    <!-- authenticationManager defined above -->
-    <bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
-        <property name="allowIfAllAbstainDecisions">
-            <value>false</value>
-        </property>
-        <property name="decisionVoters">
-            <list>
-                <ref local="roleVoter"/>
-            </list>
-        </property>
-    </bean>
-
-    <bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter"/>
-
-    <bean id="ntlmEntryPoint" class="org.springframework.security.ui.ntlm.NtlmProcessingFilterEntryPoint">
-        <property name="authenticationFailureUrl" value="/login_error.jsp"/>
-    </bean>
-
-    <!-- Done with the chain -->
-
-    <!-- This bean automatically receives AuthenticationEvent messages from DaoAuthenticationProvider -->
-    <bean id="loggerListener" class="org.springframework.security.authentication.event.LoggerListener"/>
-
-</beans>

+ 0 - 64
ntlm/pom.xml

@@ -1,64 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.springframework.security</groupId>
-        <artifactId>spring-security-parent</artifactId>
-        <version>3.0.0.CI-SNAPSHOT</version>
-    </parent>
-    <packaging>jar</packaging>
-    <artifactId>spring-security-ntlm</artifactId>
-    <name>Spring Security - NTLM support</name>
-
-    <dependencies>
-        <dependency>
-          <groupId>org.springframework.security</groupId>
-          <artifactId>spring-security-core</artifactId>
-          <version>${project.version}</version>
-        </dependency>
-        <dependency>
-          <groupId>org.springframework.security</groupId>
-          <artifactId>spring-security-web</artifactId>
-          <version>${project.version}</version>
-        </dependency>
-        <dependency>
-          <groupId>org.springframework.security</groupId>
-          <artifactId>spring-security-ldap</artifactId>
-          <version>${project.version}</version>
-        </dependency>
-        <!-- SMT NTLM-->
-        <dependency>
-            <groupId>org.samba.jcifs</groupId>
-            <artifactId>jcifs</artifactId>
-            <version>1.2.19</version>
-        </dependency>
-        <dependency>
-            <groupId>javax.servlet</groupId>
-            <artifactId>jsp-api</artifactId>
-            <version>2.0</version>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>javax.servlet</groupId>
-            <artifactId>servlet-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.ldap</groupId>
-            <artifactId>spring-ldap-core</artifactId>
-            <optional>true</optional>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${basedir}/src/main/resources</directory>
-                <targetPath>/</targetPath>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-                <filtering>false</filtering>
-            </resource>
-        </resources>
-    </build>
-
-</project>

+ 0 - 34
ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmBaseException.java

@@ -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 <code>AuthenticationException</code>s in the
- * {@link NtlmProcessingFilterEntryPoint}.  Marked as <code>abstract</code>
- * 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);
-    }
-
-}

+ 0 - 29
ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmBeginHandshakeException.java

@@ -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");
-    }
-
-}

+ 0 - 520
ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmProcessingFilter.java

@@ -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.
- * <p>
- * 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.
- * <p>
- * Because NTLM only provides the username of the Windows client, a Spring
- * Security NTLM deployment must have a <code>UserDetailsService</code> that
- * provides a <code>UserDetails</code> object with the empty string as the
- * password and whatever <code>GrantedAuthority</code> values necessary to
- * pass the <code>FilterSecurityInterceptor</code>.
- * <p>
- * The Spring Security bean configuration file must also place the
- * <code>ExceptionTranslationFilter</code> before this filter in the
- * <code>FilterChainProxy</code> 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 <code>false</code> */
-    private boolean    loadBalance;
-
-    /** Should the domain name be stripped from the username, default <code>true</code> */
-    private boolean stripDomain = true;
-
-    /** Should the filter initiate NTLM negotiations, default <code>true</code>    */
-    private boolean forceIdentification = true;
-
-    /** Should the filter retry NTLM on authorization failure, default <code>false</code> */
-    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 <code>AuthenticationManager</code> 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 <code>AuthenticationManager</code> to use.
-     *
-     * @param authenticationManager the <code>AuthenticationManager</code> 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 <code>1</code>, 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
-     * <code>domainController</code> 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 <code>true</code>, 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 <code>NtlmProcessingFilter</code> to strip the Windows
-     * domain name from the username when set to <code>true</code>, which
-     * is the default value.
-     *
-     * @param stripDomain The strip domain flag value.
-     */
-    public void setStripDomain(boolean stripDomain) {
-        this.stripDomain = stripDomain;
-    }
-
-    /**
-     * Sets the <code>jcifs.smb.client.soTimeout</code> 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 <code>jcifs.netbios.cachePolicy</code> 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 <code>true</code> if NTLM authentication is forced.
-     *
-     * @return <code>true</code> 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 <code>true</code> 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 <code>HTTPSession</code> 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 <code>NtlmPasswordAuthentication</code> object
-     * from the provided Type 3 message.
-     *
-     * @param message the Type 3 message to process.
-     * @param session the <code>HTTPSession</code> object.
-     * @param dcAddress the domain controller address.
-     * @return an <code>NtlmPasswordAuthentication</code> 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 <code>HTTPSession</code> object.
-     * @param dcAddress the domain controller address.
-     * @param auth the <code>NtlmPasswordAuthentication</code> 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 <code>AuthenticationManager</code>.
-     *
-     * @param request the <code>HttpServletRequest</code> object.
-     * @param response the <code>HttpServletResponse</code> object.
-     * @param session the <code>HttpSession</code> object.
-     * @param auth the <code>NtlmPasswordAuthentication</code> 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 <code>loadBalance</code>
-     * setting.
-     *
-     * @param session the <code>HttpSession</code> 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 <code>loadBalance</code>
-     * setting.
-     *
-     * @param session the <code>HttpSession</code> 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);
-    }
-}

+ 0 - 108
ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmProcessingFilterEntryPoint.java

@@ -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 <code>ExceptionTranslationFilter</code> 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}:
-     * <p>
-     * <ul>
-     * <li>{@link NtlmBeginHandshakeException}: NTLM
-     * <li>{@link NtlmType2MessageException}: NTLM &lt;base64-encoded type-2-message&gt;
-     * </ul>
-     *
-     * 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));
-        }
-    }
-
-}

+ 0 - 48
ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmType2MessageException.java

@@ -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 <code>Authentication</code> object each time
-     * Internet Explorer does a POST.
-     */
-    public void preserveAuthentication() {
-        if (auth != null) {
-            SecurityContextHolder.getContext().setAuthentication(auth);
-        }
-    }
-
-}

+ 0 - 59
ntlm/src/main/java/org/springframework/security/ui/ntlm/NtlmUsernamePasswordAuthenticationToken.java

@@ -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<GrantedAuthority> 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 <code>true</code>,
-     *                         otherwise use the username and domain name.
-     */
-    public NtlmUsernamePasswordAuthenticationToken(NtlmPasswordAuthentication ntlmAuth, boolean stripDomain) {
-        super((stripDomain) ? ntlmAuth.getUsername() : ntlmAuth.getName(), DEFAULT_PASSWORD, NTLM_AUTHENTICATED);
-    }
-}

+ 0 - 108
ntlm/src/main/java/org/springframework/security/ui/ntlm/ldap/authenticator/NtlmAwareLdapAuthenticator.java

@@ -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 <tt>Authentication</tt> object is of type <tt>NtlmUsernamePasswordAuthenticationToken</tt>,
-     * 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;
-    }
-}

+ 0 - 50
ntlm/src/test/java/org/springframework/security/ui/ntlm/ldap/authenticator/NtlmAwareLdapAuthenticatorTests.java

@@ -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);
-    }
-
-
-}

+ 0 - 53
ntlm/web.xml

@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
-	<display-name>Spring Security NTLM</display-name>
-
-<!-- 1. Setup two parameters:          -->
-<!--    a) Spring Security's configuration file  -->
-<!--    b) Logging configuration file   -->
-	<context-param>
-		<param-name>contextConfigLocation</param-name>
-		<param-value>/WEB-INF/applicationContext.xml</param-value>
-	</context-param>
-
-	<context-param>
-		<param-name>log4jConfigLocation</param-name>
-		<param-value>/WEB-INF/log4j.properties</param-value>
-	</context-param>
-
-<!-- 2. Setup the Spring Security Filter Chain Proxy -->
-    <filter>
-        <filter-name>filterChainProxy</filter-name>
-        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
-    </filter>
-    
-    <filter-mapping>
-        <filter-name>filterChainProxy</filter-name>
-        <url-pattern>/*</url-pattern>
-    </filter-mapping>
-    
-<!-- 3. Setup three listeners -->
-<!--    a) Setup a listener to connect spring with the web context -->
-	<listener>
-		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
-	</listener>
-
-<!--	b) Setup a listener to connect spring with log4J -->
-	<listener>
-		<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
-	</listener>
-
-<!--    c) Setup Spring Security to subscribe to http session events in the web context -->
-	<listener>
-		<listener-class>org.springframework.security.ui.session.HttpSessionEventPublisher</listener-class>
-	</listener>
-
-	<welcome-file-list>
-		<welcome-file>index.html</welcome-file>
-		<welcome-file>index.htm</welcome-file>
-		<welcome-file>index.jsp</welcome-file>
-		<welcome-file>default.html</welcome-file>
-		<welcome-file>default.htm</welcome-file>
-		<welcome-file>default.jsp</welcome-file>
-	</welcome-file-list>
-</web-app>