Forums de discussion

{Resolved Sorta] NTLM Popup - Anyway to get rid of it?

thumbnail
Chris Whittle, modifié il y a 15 années.

{Resolved Sorta] NTLM Popup - Anyway to get rid of it?

Expert Publications: 462 Date d'inscription: 17/09/08 Publications récentes
We are setting up a extranet liferay portal and internal we want to use NTLM to provide SSO but when you come in from external (or from Firefox) it gives you the NTLM popup... We want to remove that so that when NTLM fails it doesn't do anything and the user can just login from a portlet... Is this possible?
thumbnail
Chris Whittle, modifié il y a 15 années.

RE: NTLM Popup - Anyway to get rid of it?

Expert Publications: 462 Date d'inscription: 17/09/08 Publications récentes
ok I've reolved this sorta... We use internal IP addresses so what I did was create a new CustomNTLMFilter.java file from the original NTLMFilter.java and at the beginning before I try to use NTLM I check to see if the users ip is starts with 10. (this is what we use internally and before you say sppof we have a mechanism to stop external ips from coming in with the prefix 10.) and also to check to see if the user is using IE... if so it attempts to do NTLM and if not it doesn't do anything letting the user login normally.... My code is pretty basic so there is better ways to do it but I'll give it to ya anyways...

/**
 * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.ext.portlet.portal.servlet.filters.sso.ntlm;

import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.security.ldap.PortalLDAPUtil;
import com.liferay.portal.util.PortalInstances;
import com.liferay.portal.util.PrefsPropsUtil;
import com.liferay.portal.util.PropsKeys;
import com.liferay.portal.util.PropsValues;
import com.liferay.portal.util.WebKeys;
import com.liferay.util.servlet.filters.DynamicFilterConfig;

import java.io.IOException;
import java.util.regex.*;

import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
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.http.NtlmHttpFilter;
import jcifs.http.NtlmSsp;

import jcifs.ntlmssp.Type1Message;
import jcifs.ntlmssp.Type2Message;

import jcifs.smb.NtlmPasswordAuthentication;
import jcifs.smb.SmbSession;

import jcifs.util.Base64;

public class CustomNtlmFilter extends NtlmHttpFilter {

	public void init(FilterConfig filterConfig) throws ServletException {
		super.init(filterConfig);

		_filterConfig = new DynamicFilterConfig(filterConfig);
	}

	public void doFilter(
			ServletRequest servletRequest, ServletResponse servletResponse,
			FilterChain filterChain)
		throws IOException, ServletException {


		try {
			HttpServletRequest request = (HttpServletRequest)servletRequest;
			HttpServletResponse response = (HttpServletResponse)servletResponse;

			//Validates that this is an internal IP address and that it is an IE Box
			if(IPCheck(servletRequest.getRemoteAddr()) && isMSIEBrowser(request)){

				long companyId = PortalInstances.getCompanyId(request);

				if (PortalLDAPUtil.isNtlmEnabled(companyId)) {
					String domainController = _filterConfig.getInitParameter(
						"jcifs.http.domainController");
					String domain = _filterConfig.getInitParameter(
						"jcifs.smb.client.domain");

					if ((domainController == null) && (domain == null)) {
						domainController = PrefsPropsUtil.getString(
							companyId, PropsKeys.NTLM_DOMAIN_CONTROLLER,
							PropsValues.NTLM_DOMAIN_CONTROLLER);
						domain = PrefsPropsUtil.getString(
							companyId, PropsKeys.NTLM_DOMAIN,
							PropsValues.NTLM_DOMAIN);

						_filterConfig.addInitParameter(
							"jcifs.http.domainController", domainController);
						_filterConfig.addInitParameter(
							"jcifs.smb.client.domain", domain);

						super.init(_filterConfig);

						if (_log.isDebugEnabled()) {
							_log.debug("Host " + domainController);
							_log.debug("Domain " + domain);
						}
					}

					// Type 1 NTLM requests from browser can (and should) always
					// immediately be replied to with an Type 2 NTLM response, no
					// matter whether we're yet logging in or whether it is much
					// later in the session.

					String msg = request.getHeader("Authorization");

					if (msg != null && msg.startsWith("NTLM")) {
						byte[] src = Base64.decode(msg.substring(5));

						if (src[8] == 1) {
							UniAddress dc = UniAddress.getByName(
								Config.getProperty("jcifs.http.domainController"),
								true);

							byte[] challenge = SmbSession.getChallenge(dc);

							Type1Message type1 = new Type1Message(src);
							Type2Message type2 = new Type2Message(
								type1, challenge, null);

							msg = Base64.encode(type2.toByteArray());

							response.setHeader("WWW-Authenticate", "NTLM " + msg);
							response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
							response.setContentLength(0);

							response.flushBuffer();

							// Interrupt filter chain, send response. Browser will
							// immediately post a new request.

							return;
						}
					}

					String path = request.getPathInfo();

					if (path != null && path.endsWith("/login")) {
						NtlmPasswordAuthentication ntlm = negotiate(
							request, response, false);

						if (ntlm == null) {
							return;
						}

						String remoteUser = ntlm.getName();

						int pos = remoteUser.indexOf(StringPool.BACK_SLASH);

						if (pos != -1) {
							remoteUser = remoteUser.substring(pos + 1);
						}

						if (_log.isDebugEnabled()) {
							_log.debug("NTLM remote user " + remoteUser);
						}

						servletRequest.setAttribute(
							WebKeys.NTLM_REMOTE_USER, remoteUser);
					}
				}
			}
		}
		catch (Exception e) {
			_log.error(e);
		}

		filterChain.doFilter(servletRequest, servletResponse);
	}
	private boolean IPCheck(String IP){
		boolean myIPCheck = false;
		try{
			//Attempt to validate IP but could not get it to work
//			final Pattern IP_PATTERN =
//				  Pattern.compile("b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)"
//										+ "{3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)b");
//			if(IP_PATTERN.matcher(IP).matches()){

				if(IP.startsWith("10.", 0)){
					myIPCheck = true;
				}
//			}
		}catch (Exception e) {
			_log.error(e);
		}
		return myIPCheck;
	}
	private boolean isMSIEBrowser(HttpServletRequest req) {
	        // test the browser version
	        boolean isIE = false;

	        if (userAgent == null) {
	                // No info
	        }
	        else {
	                if (userAgent.indexOf("MSIE") >= 0) {
	                        // the string MSIE in included in the user-agent
	                        isIE = true;
	                }
	        }

        return isIE;
	}

	public NtlmPasswordAuthentication negotiate(
			HttpServletRequest request, HttpServletResponse response,
			boolean skipAuthentication)
		throws IOException, ServletException {

		NtlmPasswordAuthentication ntlm = null;

		HttpSession session = request.getSession(false);

		String authorizationHeader = request.getHeader("Authorization");

		if (_log.isDebugEnabled()) {
			_log.debug("Authorization header " + authorizationHeader);
		}

		if ((authorizationHeader != null) && (
			(authorizationHeader.startsWith("NTLM ")))) {

			String domainController = Config.getProperty(
				"jcifs.http.domainController");

			UniAddress uniAddress = UniAddress.getByName(
				domainController, true);

			if (_log.isDebugEnabled()) {
				_log.debug("Address " + uniAddress);
			}

			byte[] challenge = SmbSession.getChallenge(uniAddress);

			ntlm = NtlmSsp.authenticate(request, response, challenge);

			session.setAttribute("NtlmHttpAuth", ntlm);
		}
		else {
			if (session != null) {
				ntlm = (NtlmPasswordAuthentication)session.getAttribute(
					"NtlmHttpAuth");
			}

			if (ntlm == null) {
				response.setHeader("WWW-Authenticate", "NTLM");
				response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
				response.setContentLength(0);

				response.flushBuffer();

				return null;
			}
		}

		if (_log.isDebugEnabled()) {
			_log.debug("Password authentication " + ntlm);
		}

		return ntlm;
	}

	private static Log _log = LogFactoryUtil.getLog(CustomNtlmFilter.class);

	private DynamicFilterConfig _filterConfig;

}