001
014
015 package com.liferay.portal.servlet.filters.sso.ntlm;
016
017 import com.liferay.portal.kernel.cache.PortalCache;
018 import com.liferay.portal.kernel.cache.SingleVMPoolUtil;
019 import com.liferay.portal.kernel.exception.SystemException;
020 import com.liferay.portal.kernel.io.BigEndianCodec;
021 import com.liferay.portal.kernel.log.Log;
022 import com.liferay.portal.kernel.log.LogFactoryUtil;
023 import com.liferay.portal.kernel.security.SecureRandomUtil;
024 import com.liferay.portal.kernel.servlet.BrowserSnifferUtil;
025 import com.liferay.portal.kernel.servlet.HttpHeaders;
026 import com.liferay.portal.kernel.util.GetterUtil;
027 import com.liferay.portal.kernel.util.PropsKeys;
028 import com.liferay.portal.kernel.util.Validator;
029 import com.liferay.portal.security.auth.AuthSettingsUtil;
030 import com.liferay.portal.security.ntlm.NtlmManager;
031 import com.liferay.portal.security.ntlm.NtlmUserAccount;
032 import com.liferay.portal.servlet.filters.BasePortalFilter;
033 import com.liferay.portal.util.PortalInstances;
034 import com.liferay.portal.util.PrefsPropsUtil;
035 import com.liferay.portal.util.PropsUtil;
036 import com.liferay.portal.util.PropsValues;
037 import com.liferay.portal.util.WebKeys;
038
039 import java.util.Map;
040 import java.util.Properties;
041 import java.util.concurrent.ConcurrentHashMap;
042
043 import javax.servlet.FilterChain;
044 import javax.servlet.FilterConfig;
045 import javax.servlet.http.HttpServletRequest;
046 import javax.servlet.http.HttpServletResponse;
047 import javax.servlet.http.HttpSession;
048
049 import jcifs.Config;
050
051 import jcifs.util.Base64;
052
053
061 public class NtlmFilter extends BasePortalFilter {
062
063 @Override
064 public void init(FilterConfig filterConfig) {
065 super.init(filterConfig);
066
067 try {
068 Properties properties = PropsUtil.getProperties("jcifs.", false);
069
070 for (Map.Entry<Object, Object> entry : properties.entrySet()) {
071 String key = (String)entry.getKey();
072 String value = (String)entry.getValue();
073
074 Config.setProperty(key, value);
075 }
076 }
077 catch (Exception e) {
078 _log.error(e, e);
079 }
080 }
081
082 @Override
083 public boolean isFilterEnabled(
084 HttpServletRequest request, HttpServletResponse response) {
085
086 try {
087 long companyId = PortalInstances.getCompanyId(request);
088
089 if (BrowserSnifferUtil.isIe(request) &&
090 AuthSettingsUtil.isNtlmEnabled(companyId)) {
091
092 return true;
093 }
094 }
095 catch (Exception e) {
096 _log.error(e, e);
097 }
098
099 return false;
100 }
101
102 @Override
103 protected Log getLog() {
104 return _log;
105 }
106
107 protected NtlmManager getNtlmManager(long companyId)
108 throws SystemException {
109
110 String domain = PrefsPropsUtil.getString(
111 companyId, PropsKeys.NTLM_DOMAIN, PropsValues.NTLM_DOMAIN);
112 String domainController = PrefsPropsUtil.getString(
113 companyId, PropsKeys.NTLM_DOMAIN_CONTROLLER,
114 PropsValues.NTLM_DOMAIN_CONTROLLER);
115 String domainControllerName = PrefsPropsUtil.getString(
116 companyId, PropsKeys.NTLM_DOMAIN_CONTROLLER_NAME,
117 PropsValues.NTLM_DOMAIN_CONTROLLER_NAME);
118 String serviceAccount = PrefsPropsUtil.getString(
119 companyId, PropsKeys.NTLM_SERVICE_ACCOUNT,
120 PropsValues.NTLM_SERVICE_ACCOUNT);
121 String servicePassword = PrefsPropsUtil.getString(
122 companyId, PropsKeys.NTLM_SERVICE_PASSWORD,
123 PropsValues.NTLM_SERVICE_PASSWORD);
124
125 NtlmManager ntlmManager = _ntlmManagers.get(companyId);
126
127 if (ntlmManager == null) {
128 ntlmManager = new NtlmManager(
129 domain, domainController, domainControllerName, serviceAccount,
130 servicePassword);
131
132 _ntlmManagers.put(companyId, ntlmManager);
133 }
134 else {
135 if (!Validator.equals(ntlmManager.getDomain(), domain) ||
136 !Validator.equals(
137 ntlmManager.getDomainController(), domainController) ||
138 !Validator.equals(
139 ntlmManager.getDomainControllerName(),
140 domainControllerName) ||
141 !Validator.equals(
142 ntlmManager.getServiceAccount(), serviceAccount) ||
143 !Validator.equals(
144 ntlmManager.getServicePassword(), servicePassword)) {
145
146 ntlmManager.setConfiguration(
147 domain, domainController, domainControllerName,
148 serviceAccount, servicePassword);
149 }
150 }
151
152 return ntlmManager;
153 }
154
155 protected String getPortalCacheKey(HttpServletRequest request) {
156 HttpSession session = request.getSession(false);
157
158 if (session == null) {
159 return request.getRemoteAddr();
160 }
161
162 return session.getId();
163 }
164
165 @Override
166 protected void processFilter(
167 HttpServletRequest request, HttpServletResponse response,
168 FilterChain filterChain)
169 throws Exception {
170
171
172
173
174
175 HttpSession session = request.getSession(false);
176
177 long companyId = PortalInstances.getCompanyId(request);
178
179 String authorization = GetterUtil.getString(
180 request.getHeader(HttpHeaders.AUTHORIZATION));
181
182 if (authorization.startsWith("NTLM")) {
183 NtlmManager ntlmManager = getNtlmManager(companyId);
184
185 String portalCacheKey = getPortalCacheKey(request);
186
187 byte[] src = Base64.decode(authorization.substring(5));
188
189 if (src[8] == 1) {
190 byte[] serverChallenge = new byte[8];
191
192 BigEndianCodec.putLong(
193 serverChallenge, 0, SecureRandomUtil.nextLong());
194
195 byte[] challengeMessage = ntlmManager.negotiate(
196 src, serverChallenge);
197
198 authorization = Base64.encode(challengeMessage);
199
200 response.setContentLength(0);
201 response.setHeader(
202 HttpHeaders.WWW_AUTHENTICATE, "NTLM " + authorization);
203 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
204
205 response.flushBuffer();
206
207 _portalCache.put(portalCacheKey, serverChallenge);
208
209
210
211
212 return;
213 }
214
215 byte[] serverChallenge = _portalCache.get(portalCacheKey);
216
217 if (serverChallenge == null) {
218 response.setContentLength(0);
219 response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "NTLM");
220 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
221
222 response.flushBuffer();
223
224 return;
225 }
226
227 NtlmUserAccount ntlmUserAccount = null;
228
229 try {
230 ntlmUserAccount = ntlmManager.authenticate(
231 src, serverChallenge);
232 }
233 catch (Exception e) {
234 if (_log.isErrorEnabled()) {
235 _log.error("Unable to perform NTLM authentication", e);
236 }
237 }
238 finally {
239 _portalCache.remove(portalCacheKey);
240 }
241
242 if (ntlmUserAccount == null) {
243 response.setContentLength(0);
244 response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "NTLM");
245 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
246
247 response.flushBuffer();
248
249 return;
250 }
251
252 if (_log.isDebugEnabled()) {
253 _log.debug("NTLM remote user " + ntlmUserAccount.getUserName());
254 }
255
256 request.setAttribute(
257 WebKeys.NTLM_REMOTE_USER, ntlmUserAccount.getUserName());
258
259 if (session != null) {
260 session.setAttribute(
261 WebKeys.NTLM_USER_ACCOUNT, ntlmUserAccount);
262 }
263 }
264
265 String path = request.getPathInfo();
266
267 if ((path != null) && path.endsWith("/login")) {
268 NtlmUserAccount ntlmUserAccount = null;
269
270 if (session != null) {
271 ntlmUserAccount = (NtlmUserAccount)session.getAttribute(
272 WebKeys.NTLM_USER_ACCOUNT);
273 }
274
275 if (ntlmUserAccount == null) {
276 response.setContentLength(0);
277 response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "NTLM");
278 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
279
280 response.flushBuffer();
281
282 return;
283 }
284 else {
285 request.setAttribute(
286 WebKeys.NTLM_REMOTE_USER, ntlmUserAccount.getUserName());
287 }
288 }
289
290 processFilter(NtlmPostFilter.class, request, response, filterChain);
291 }
292
293 private static Log _log = LogFactoryUtil.getLog(NtlmFilter.class);
294
295 private Map<Long, NtlmManager> _ntlmManagers =
296 new ConcurrentHashMap<Long, NtlmManager>();
297 private PortalCache<String, byte[]> _portalCache =
298 SingleVMPoolUtil.getCache(NtlmFilter.class.getName());
299
300 }