001
014
015 package com.liferay.portal.security.auth;
016
017 import com.liferay.portal.NoSuchUserException;
018 import com.liferay.portal.PasswordExpiredException;
019 import com.liferay.portal.UserLockoutException;
020 import com.liferay.portal.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022 import com.liferay.portal.kernel.util.PropsKeys;
023 import com.liferay.portal.kernel.util.StringPool;
024 import com.liferay.portal.kernel.util.StringUtil;
025 import com.liferay.portal.kernel.util.Validator;
026 import com.liferay.portal.model.User;
027 import com.liferay.portal.security.ldap.LDAPSettingsUtil;
028 import com.liferay.portal.security.ldap.PortalLDAPImporterUtil;
029 import com.liferay.portal.security.ldap.PortalLDAPUtil;
030 import com.liferay.portal.security.pwd.PwdEncryptor;
031 import com.liferay.portal.service.UserLocalServiceUtil;
032 import com.liferay.portal.util.PrefsPropsUtil;
033 import com.liferay.portal.util.PropsValues;
034 import com.liferay.portlet.admin.util.OmniadminUtil;
035
036 import java.util.Hashtable;
037 import java.util.Map;
038
039 import javax.naming.Context;
040 import javax.naming.NamingEnumeration;
041 import javax.naming.directory.Attribute;
042 import javax.naming.directory.Attributes;
043 import javax.naming.directory.SearchControls;
044 import javax.naming.directory.SearchResult;
045 import javax.naming.ldap.Control;
046 import javax.naming.ldap.InitialLdapContext;
047 import javax.naming.ldap.LdapContext;
048
049
053 public class LDAPAuth implements Authenticator {
054
055 public static final String AUTH_METHOD_BIND = "bind";
056
057 public static final String AUTH_METHOD_PASSWORD_COMPARE =
058 "password-compare";
059
060 public static final String RESULT_PASSWORD_EXP_WARNING =
061 "2.16.840.1.113730.3.4.5";
062
063 public static final String RESULT_PASSWORD_RESET =
064 "2.16.840.1.113730.3.4.4";
065
066 public int authenticateByEmailAddress(
067 long companyId, String emailAddress, String password,
068 Map<String, String[]> headerMap, Map<String, String[]> parameterMap)
069 throws AuthException {
070
071 try {
072 return authenticate(
073 companyId, emailAddress, StringPool.BLANK, 0, password);
074 }
075 catch (Exception e) {
076 _log.error(e, e);
077
078 throw new AuthException(e);
079 }
080 }
081
082 public int authenticateByScreenName(
083 long companyId, String screenName, String password,
084 Map<String, String[]> headerMap, Map<String, String[]> parameterMap)
085 throws AuthException {
086
087 try {
088 return authenticate(
089 companyId, StringPool.BLANK, screenName, 0, password);
090 }
091 catch (Exception e) {
092 _log.error(e, e);
093
094 throw new AuthException(e);
095 }
096 }
097
098 public int authenticateByUserId(
099 long companyId, long userId, String password,
100 Map<String, String[]> headerMap, Map<String, String[]> parameterMap)
101 throws AuthException {
102
103 try {
104 return authenticate(
105 companyId, StringPool.BLANK, StringPool.BLANK, userId,
106 password);
107 }
108 catch (Exception e) {
109 _log.error(e, e);
110
111 throw new AuthException(e);
112 }
113 }
114
115 protected LDAPAuthResult authenticate(
116 LdapContext ctx, long companyId, Attributes attributes,
117 String userDN, String password)
118 throws Exception {
119
120 LDAPAuthResult ldapAuthResult = new LDAPAuthResult();
121
122
123
124
125
126 String authMethod = PrefsPropsUtil.getString(
127 companyId, PropsKeys.LDAP_AUTH_METHOD);
128 InitialLdapContext innerCtx = null;
129
130 if (authMethod.equals(AUTH_METHOD_BIND)) {
131 try {
132 Hashtable<String, Object> env =
133 (Hashtable<String, Object>)ctx.getEnvironment();
134
135 env.put(Context.SECURITY_PRINCIPAL, userDN);
136 env.put(Context.SECURITY_CREDENTIALS, password);
137 env.put(
138 Context.REFERRAL,
139 PrefsPropsUtil.getString(
140 companyId, PropsKeys.LDAP_REFERRAL));
141
142
143
144 env.put("com.sun.jndi.ldap.connect.pool", "false");
145
146 innerCtx = new InitialLdapContext(env, null);
147
148
149
150 Control[] responseControls = innerCtx.getResponseControls();
151
152 ldapAuthResult.setAuthenticated(true);
153 ldapAuthResult.setResponseControl(responseControls);
154 }
155 catch (Exception e) {
156 if (_log.isDebugEnabled()) {
157 _log.debug(
158 "Failed to bind to the LDAP server with userDN "
159 + userDN + " and password " + password);
160 }
161
162 _log.error("Failed to bind to the LDAP server", e);
163
164 ldapAuthResult.setAuthenticated(false);
165 ldapAuthResult.setErrorMessage(e.getMessage());
166 }
167 finally {
168 if (innerCtx != null) {
169 innerCtx.close();
170 }
171 }
172 }
173 else if (authMethod.equals(AUTH_METHOD_PASSWORD_COMPARE)) {
174 Attribute userPassword = attributes.get("userPassword");
175
176 if (userPassword != null) {
177 String ldapPassword = new String((byte[])userPassword.get());
178
179 String encryptedPassword = password;
180
181 String algorithm = PrefsPropsUtil.getString(
182 companyId,
183 PropsKeys.LDAP_AUTH_PASSWORD_ENCRYPTION_ALGORITHM);
184
185 if (Validator.isNotNull(algorithm)) {
186 encryptedPassword =
187 "{" + algorithm + "}" +
188 PwdEncryptor.encrypt(
189 algorithm, password, ldapPassword);
190 }
191
192 if (ldapPassword.equals(encryptedPassword)) {
193 ldapAuthResult.setAuthenticated(true);
194 }
195 else {
196 ldapAuthResult.setAuthenticated(false);
197
198 if (_log.isWarnEnabled()) {
199 _log.warn(
200 "Passwords do not match for userDN " + userDN);
201 }
202 }
203 }
204 }
205
206 return ldapAuthResult;
207 }
208
209 protected int authenticate(
210 long companyId, long ldapServerId, String emailAddress,
211 String screenName, long userId, String password)
212 throws Exception {
213
214 String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
215
216 LdapContext ldapContext = PortalLDAPUtil.getContext(
217 ldapServerId, companyId);
218
219 if (ldapContext == null) {
220 return FAILURE;
221 }
222
223 try {
224 String baseDN = PrefsPropsUtil.getString(
225 companyId, PropsKeys.LDAP_BASE_DN + postfix);
226
227
228
229 String filter = LDAPSettingsUtil.getAuthSearchFilter(
230 ldapServerId, companyId, emailAddress, screenName,
231 String.valueOf(userId));
232
233 SearchControls searchControls = new SearchControls(
234 SearchControls.SUBTREE_SCOPE, 1, 0, null, false, false);
235
236 NamingEnumeration<SearchResult> enu = ldapContext.search(
237 baseDN, filter, searchControls);
238
239 if (enu.hasMoreElements()) {
240 if (_log.isDebugEnabled()) {
241 _log.debug("Search filter returned at least one result");
242 }
243
244 SearchResult result = enu.nextElement();
245
246 String fullUserDN = PortalLDAPUtil.getNameInNamespace(
247 ldapServerId, companyId, result);
248
249 Attributes attributes = PortalLDAPUtil.getUserAttributes(
250 ldapServerId, companyId, ldapContext, fullUserDN);
251
252 LDAPAuthResult ldapAuthResult = authenticate(
253 ldapContext, companyId, attributes, fullUserDN, password);
254
255
256
257 String errorMessage = ldapAuthResult.getErrorMessage();
258
259 if (errorMessage != null) {
260 if (errorMessage.indexOf(PrefsPropsUtil.getString(
261 companyId, PropsKeys.LDAP_ERROR_USER_LOCKOUT))
262 != -1) {
263
264 throw new UserLockoutException();
265 }
266 else if (errorMessage.indexOf(PrefsPropsUtil.getString(
267 companyId, PropsKeys.LDAP_ERROR_PASSWORD_EXPIRED))
268 != -1) {
269
270 throw new PasswordExpiredException();
271 }
272 }
273
274 if (!ldapAuthResult.isAuthenticated()) {
275 return FAILURE;
276 }
277
278
279
280 User user = PortalLDAPImporterUtil.importLDAPUser(
281 ldapServerId, companyId, ldapContext, attributes, password);
282
283
284
285 String resultCode = ldapAuthResult.getResponseControl();
286
287 if (resultCode.equals(LDAPAuth.RESULT_PASSWORD_RESET)) {
288 UserLocalServiceUtil.updatePasswordReset(
289 user.getUserId(), true);
290 }
291 else if (
292 resultCode.equals(LDAPAuth.RESULT_PASSWORD_EXP_WARNING)) {
293
294 UserLocalServiceUtil.updatePasswordReset(
295 user.getUserId(), true);
296 }
297 }
298 else {
299 if (_log.isDebugEnabled()) {
300 _log.debug("Search filter did not return any results");
301 }
302
303 return DNE;
304 }
305
306 enu.close();
307 }
308 catch (Exception e) {
309 _log.error("Problem accessing LDAP server", e);
310
311 return FAILURE;
312 }
313 finally {
314 if (ldapContext != null) {
315 ldapContext.close();
316 }
317 }
318
319 return SUCCESS;
320 }
321
322 protected int authenticate(
323 long companyId, String emailAddress, String screenName, long userId,
324 String password)
325 throws Exception {
326
327 if (!LDAPSettingsUtil.isAuthEnabled(companyId)) {
328 if (_log.isDebugEnabled()) {
329 _log.debug("Authenticator is not enabled");
330 }
331
332 return SUCCESS;
333 }
334
335 if (_log.isDebugEnabled()) {
336 _log.debug("Authenticator is enabled");
337 }
338
339 long[] ldapServerIds = StringUtil.split(
340 PrefsPropsUtil.getString(companyId, "ldap.server.ids"), 0L);
341
342 if (ldapServerIds.length <= 0) {
343 ldapServerIds = new long[] {0};
344 }
345
346 for (long ldapServerId : ldapServerIds) {
347 int result = authenticate(
348 companyId, ldapServerId, emailAddress, screenName, userId,
349 password);
350
351 if (result == SUCCESS) {
352 return result;
353 }
354 }
355
356 return authenticateRequired(
357 companyId, userId, emailAddress, screenName, true, FAILURE);
358 }
359
360 protected int authenticateOmniadmin(
361 long companyId, String emailAddress, String screenName, long userId)
362 throws Exception {
363
364
365
366 if (PropsValues.AUTH_PIPELINE_ENABLE_LIFERAY_CHECK) {
367 if (userId > 0) {
368 if (OmniadminUtil.isOmniadmin(userId)) {
369 return SUCCESS;
370 }
371 }
372 else if (Validator.isNotNull(emailAddress)) {
373 try {
374 User user = UserLocalServiceUtil.getUserByEmailAddress(
375 companyId, emailAddress);
376
377 if (OmniadminUtil.isOmniadmin(user.getUserId())) {
378 return SUCCESS;
379 }
380 }
381 catch (NoSuchUserException nsue) {
382 }
383 }
384 else if (Validator.isNotNull(screenName)) {
385 try {
386 User user = UserLocalServiceUtil.getUserByScreenName(
387 companyId, screenName);
388
389 if (OmniadminUtil.isOmniadmin(user.getUserId())) {
390 return SUCCESS;
391 }
392 }
393 catch (NoSuchUserException nsue) {
394 }
395 }
396 }
397
398 return FAILURE;
399 }
400
401 protected int authenticateRequired(
402 long companyId, long userId, String emailAddress, String screenName,
403 boolean allowOmniadmin, int failureCode)
404 throws Exception {
405
406
407
408
409 if (allowOmniadmin &&
410 (authenticateOmniadmin(
411 companyId, emailAddress, screenName, userId) == SUCCESS)) {
412
413 return SUCCESS;
414 }
415
416 if (PrefsPropsUtil.getBoolean(
417 companyId, PropsKeys.LDAP_AUTH_REQUIRED)) {
418
419 return failureCode;
420 }
421 else {
422 return SUCCESS;
423 }
424 }
425
426 private static Log _log = LogFactoryUtil.getLog(LDAPAuth.class);
427
428 }