1
14
15 package com.liferay.portal.security.auth;
16
17 import com.liferay.portal.NoSuchUserException;
18 import com.liferay.portal.PasswordExpiredException;
19 import com.liferay.portal.UserLockoutException;
20 import com.liferay.portal.kernel.log.Log;
21 import com.liferay.portal.kernel.log.LogFactoryUtil;
22 import com.liferay.portal.kernel.util.PropsKeys;
23 import com.liferay.portal.kernel.util.StringPool;
24 import com.liferay.portal.kernel.util.StringUtil;
25 import com.liferay.portal.kernel.util.Validator;
26 import com.liferay.portal.model.User;
27 import com.liferay.portal.security.ldap.LDAPSettingsUtil;
28 import com.liferay.portal.security.ldap.PortalLDAPImporterUtil;
29 import com.liferay.portal.security.ldap.PortalLDAPUtil;
30 import com.liferay.portal.security.pwd.PwdEncryptor;
31 import com.liferay.portal.service.UserLocalServiceUtil;
32 import com.liferay.portal.util.PrefsPropsUtil;
33 import com.liferay.portal.util.PropsValues;
34 import com.liferay.portlet.admin.util.OmniadminUtil;
35
36 import java.util.Hashtable;
37 import java.util.Map;
38
39 import javax.naming.Context;
40 import javax.naming.NamingEnumeration;
41 import javax.naming.directory.Attribute;
42 import javax.naming.directory.Attributes;
43 import javax.naming.directory.SearchControls;
44 import javax.naming.directory.SearchResult;
45 import javax.naming.ldap.Control;
46 import javax.naming.ldap.InitialLdapContext;
47 import javax.naming.ldap.LdapContext;
48
49
55 public class LDAPAuth implements Authenticator {
56
57 public static final String AUTH_METHOD_BIND = "bind";
58
59 public static final String AUTH_METHOD_PASSWORD_COMPARE =
60 "password-compare";
61
62 public static final String RESULT_PASSWORD_EXP_WARNING =
63 "2.16.840.1.113730.3.4.5";
64
65 public static final String RESULT_PASSWORD_RESET =
66 "2.16.840.1.113730.3.4.4";
67
68 public int authenticateByEmailAddress(
69 long companyId, String emailAddress, String password,
70 Map<String, String[]> headerMap, Map<String, String[]> parameterMap)
71 throws AuthException {
72
73 try {
74 return authenticate(
75 companyId, emailAddress, StringPool.BLANK, 0, password);
76 }
77 catch (Exception e) {
78 _log.error(e, e);
79
80 throw new AuthException(e);
81 }
82 }
83
84 public int authenticateByScreenName(
85 long companyId, String screenName, String password,
86 Map<String, String[]> headerMap, Map<String, String[]> parameterMap)
87 throws AuthException {
88
89 try {
90 return authenticate(
91 companyId, StringPool.BLANK, screenName, 0, password);
92 }
93 catch (Exception e) {
94 _log.error(e, e);
95
96 throw new AuthException(e);
97 }
98 }
99
100 public int authenticateByUserId(
101 long companyId, long userId, String password,
102 Map<String, String[]> headerMap, Map<String, String[]> parameterMap)
103 throws AuthException {
104
105 try {
106 return authenticate(
107 companyId, StringPool.BLANK, StringPool.BLANK, userId,
108 password);
109 }
110 catch (Exception e) {
111 _log.error(e, e);
112
113 throw new AuthException(e);
114 }
115 }
116
117 protected LDAPAuthResult authenticate(
118 LdapContext ctx, long companyId, Attributes attrs, String userDN,
119 String password)
120 throws Exception {
121
122 LDAPAuthResult ldapAuthResult = new LDAPAuthResult();
123
124
128 String authMethod = PrefsPropsUtil.getString(
129 companyId, PropsKeys.LDAP_AUTH_METHOD);
130 InitialLdapContext innerCtx = null;
131
132 if (authMethod.equals(AUTH_METHOD_BIND)) {
133 try {
134 Hashtable<String, Object> env =
135 (Hashtable<String, Object>)ctx.getEnvironment();
136
137 env.put(Context.SECURITY_PRINCIPAL, userDN);
138 env.put(Context.SECURITY_CREDENTIALS, password);
139 env.put(
140 Context.REFERRAL,
141 PrefsPropsUtil.getString(
142 companyId, PropsKeys.LDAP_REFERRAL));
143
144
146 env.put("com.sun.jndi.ldap.connect.pool", "false");
147
148 innerCtx = new InitialLdapContext(env, null);
149
150
152 Control[] responseControls = innerCtx.getResponseControls();
153
154 ldapAuthResult.setAuthenticated(true);
155 ldapAuthResult.setResponseControl(responseControls);
156 }
157 catch (Exception e) {
158 if (_log.isDebugEnabled()) {
159 _log.debug(
160 "Failed to bind to the LDAP server with userDN "
161 + userDN + " and password " + password);
162 }
163
164 _log.error(
165 "Failed to bind to the LDAP server: " + e.getMessage());
166
167 ldapAuthResult.setAuthenticated(false);
168 ldapAuthResult.setErrorMessage(e.getMessage());
169 }
170 finally {
171 if (innerCtx != null) {
172 innerCtx.close();
173 }
174 }
175 }
176 else if (authMethod.equals(AUTH_METHOD_PASSWORD_COMPARE)) {
177 Attribute userPassword = attrs.get("userPassword");
178
179 if (userPassword != null) {
180 String ldapPassword = new String((byte[])userPassword.get());
181
182 String encryptedPassword = password;
183
184 String algorithm = PrefsPropsUtil.getString(
185 companyId,
186 PropsKeys.LDAP_AUTH_PASSWORD_ENCRYPTION_ALGORITHM);
187
188 if (Validator.isNotNull(algorithm)) {
189 encryptedPassword =
190 "{" + algorithm + "}" +
191 PwdEncryptor.encrypt(
192 algorithm, password, ldapPassword);
193 }
194
195 if (ldapPassword.equals(encryptedPassword)) {
196 ldapAuthResult.setAuthenticated(true);
197 }
198 else {
199 ldapAuthResult.setAuthenticated(false);
200
201 if (_log.isWarnEnabled()) {
202 _log.warn(
203 "Passwords do not match for userDN " + userDN);
204 }
205 }
206 }
207 }
208
209 return ldapAuthResult;
210 }
211
212 protected int authenticate(
213 long companyId, long ldapServerId, String emailAddress,
214 String screenName, long userId, String password)
215 throws Exception {
216
217 String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
218
219 LdapContext ctx = PortalLDAPUtil.getContext(ldapServerId, companyId);
220
221 if (ctx == null) {
222 return FAILURE;
223 }
224
225 try {
226 String baseDN = PrefsPropsUtil.getString(
227 companyId, PropsKeys.LDAP_BASE_DN + postfix);
228
229
231 String filter = LDAPSettingsUtil.getAuthSearchFilter(
232 ldapServerId, companyId, emailAddress, screenName,
233 String.valueOf(userId));
234
235 SearchControls cons = new SearchControls(
236 SearchControls.SUBTREE_SCOPE, 1, 0, null, false, false);
237
238 NamingEnumeration<SearchResult> enu = ctx.search(
239 baseDN, filter, cons);
240
241 if (enu.hasMoreElements()) {
242 if (_log.isDebugEnabled()) {
243 _log.debug("Search filter returned at least one result");
244 }
245
246 SearchResult result = enu.nextElement();
247
248 String fullUserDN = PortalLDAPUtil.getNameInNamespace(
249 ldapServerId, companyId, result);
250
251 Attributes attrs = PortalLDAPUtil.getUserAttributes(
252 ldapServerId, companyId, ctx, fullUserDN);
253
254 LDAPAuthResult ldapAuthResult = authenticate(
255 ctx, companyId, attrs, fullUserDN, password);
256
257
259 String errorMessage = ldapAuthResult.getErrorMessage();
260
261 if (errorMessage != null) {
262 if (errorMessage.indexOf(PrefsPropsUtil.getString(
263 companyId, PropsKeys.LDAP_ERROR_USER_LOCKOUT))
264 != -1) {
265
266 throw new UserLockoutException();
267 }
268 else if (errorMessage.indexOf(PrefsPropsUtil.getString(
269 companyId, PropsKeys.LDAP_ERROR_PASSWORD_EXPIRED))
270 != -1) {
271
272 throw new PasswordExpiredException();
273 }
274 }
275
276 if (!ldapAuthResult.isAuthenticated()) {
277 return FAILURE;
278 }
279
280
282 User user = PortalLDAPImporterUtil.importLDAPUser(
283 ldapServerId, companyId, ctx, attrs, password, true);
284
285
287 String resultCode = ldapAuthResult.getResponseControl();
288
289 if (resultCode.equals(LDAPAuth.RESULT_PASSWORD_RESET)) {
290 UserLocalServiceUtil.updatePasswordReset(
291 user.getUserId(), true);
292 }
293 else if (
294 resultCode.equals(LDAPAuth.RESULT_PASSWORD_EXP_WARNING)) {
295
296 UserLocalServiceUtil.updatePasswordReset(
297 user.getUserId(), true);
298 }
299 }
300 else {
301 if (_log.isDebugEnabled()) {
302 _log.debug("Search filter did not return any results");
303 }
304
305 return DNE;
306 }
307
308 enu.close();
309 }
310 catch (Exception e) {
311 _log.error("Problem accessing LDAP server", e);
312
313 return FAILURE;
314 }
315 finally {
316 if (ctx != null) {
317 ctx.close();
318 }
319 }
320
321 return SUCCESS;
322 }
323
324 protected int authenticate(
325 long companyId, String emailAddress, String screenName, long userId,
326 String password)
327 throws Exception {
328
329 if (!LDAPSettingsUtil.isAuthEnabled(companyId)) {
330 if (_log.isDebugEnabled()) {
331 _log.debug("Authenticator is not enabled");
332 }
333
334 return SUCCESS;
335 }
336
337 if (_log.isDebugEnabled()) {
338 _log.debug("Authenticator is enabled");
339 }
340
341 long[] ldapServerIds = StringUtil.split(
342 PrefsPropsUtil.getString(companyId, "ldap.server.ids"), 0L);
343
344 if (ldapServerIds.length <= 0) {
345 ldapServerIds = new long[] {0};
346 }
347
348 for (long ldapServerId : ldapServerIds) {
349 int result = authenticate(
350 companyId, ldapServerId, emailAddress, screenName, userId,
351 password);
352
353 if (result == SUCCESS) {
354 return result;
355 }
356 }
357
358 return authenticateRequired(
359 companyId, userId, emailAddress, screenName, true, FAILURE);
360 }
361
362 protected int authenticateOmniadmin(
363 long companyId, String emailAddress, String screenName, long userId)
364 throws Exception {
365
366
368 if (PropsValues.AUTH_PIPELINE_ENABLE_LIFERAY_CHECK) {
369 if (userId > 0) {
370 if (OmniadminUtil.isOmniadmin(userId)) {
371 return SUCCESS;
372 }
373 }
374 else if (Validator.isNotNull(emailAddress)) {
375 try {
376 User user = UserLocalServiceUtil.getUserByEmailAddress(
377 companyId, emailAddress);
378
379 if (OmniadminUtil.isOmniadmin(user.getUserId())) {
380 return SUCCESS;
381 }
382 }
383 catch (NoSuchUserException nsue) {
384 }
385 }
386 else if (Validator.isNotNull(screenName)) {
387 try {
388 User user = UserLocalServiceUtil.getUserByScreenName(
389 companyId, screenName);
390
391 if (OmniadminUtil.isOmniadmin(user.getUserId())) {
392 return SUCCESS;
393 }
394 }
395 catch (NoSuchUserException nsue) {
396 }
397 }
398 }
399
400 return FAILURE;
401 }
402
403 protected int authenticateRequired(
404 long companyId, long userId, String emailAddress, String screenName,
405 boolean allowOmniadmin, int failureCode)
406 throws Exception {
407
408
411 if (allowOmniadmin &&
412 (authenticateOmniadmin(
413 companyId, emailAddress, screenName, userId) == SUCCESS)) {
414
415 return SUCCESS;
416 }
417
418 if (PrefsPropsUtil.getBoolean(
419 companyId, PropsKeys.LDAP_AUTH_REQUIRED)) {
420
421 return failureCode;
422 }
423 else {
424 return SUCCESS;
425 }
426 }
427
428 private static Log _log = LogFactoryUtil.getLog(LDAPAuth.class);
429
430 }