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