001
014
015 package com.liferay.portal.security.ldap;
016
017 import com.liferay.portal.kernel.exception.SystemException;
018 import com.liferay.portal.kernel.log.Log;
019 import com.liferay.portal.kernel.log.LogFactoryUtil;
020 import com.liferay.portal.kernel.util.GetterUtil;
021 import com.liferay.portal.kernel.util.PropsKeys;
022 import com.liferay.portal.kernel.util.StringBundler;
023 import com.liferay.portal.kernel.util.StringPool;
024 import com.liferay.portal.kernel.util.Validator;
025 import com.liferay.portal.model.Contact;
026 import com.liferay.portal.model.Image;
027 import com.liferay.portal.model.User;
028 import com.liferay.portal.model.UserGroup;
029 import com.liferay.portal.security.pwd.PasswordEncryptorUtil;
030 import com.liferay.portal.service.ImageLocalServiceUtil;
031 import com.liferay.portal.util.PrefsPropsUtil;
032 import com.liferay.portlet.expando.model.ExpandoBridge;
033 import com.liferay.portlet.expando.util.ExpandoConverterUtil;
034
035 import java.io.Serializable;
036
037 import java.util.HashMap;
038 import java.util.List;
039 import java.util.Map;
040 import java.util.Properties;
041
042 import javax.naming.Binding;
043 import javax.naming.directory.Attribute;
044 import javax.naming.directory.Attributes;
045 import javax.naming.directory.BasicAttribute;
046 import javax.naming.directory.BasicAttributes;
047 import javax.naming.directory.DirContext;
048
049 import org.apache.commons.beanutils.PropertyUtils;
050
051
057 public class DefaultPortalToLDAPConverter implements PortalToLDAPConverter {
058
059 public DefaultPortalToLDAPConverter() {
060 _reservedUserFieldNames.put(
061 UserConverterKeys.GROUP, UserConverterKeys.GROUP);
062 _reservedUserFieldNames.put(
063 UserConverterKeys.PASSWORD, UserConverterKeys.PASSWORD);
064 _reservedUserFieldNames.put(
065 UserConverterKeys.PORTRAIT, UserConverterKeys.PORTRAIT);
066 _reservedUserFieldNames.put(
067 UserConverterKeys.SCREEN_NAME, UserConverterKeys.SCREEN_NAME);
068 }
069
070 @Override
071 public String getGroupDNName(
072 long ldapServerId, UserGroup userGroup, Properties groupMappings)
073 throws Exception {
074
075 Binding groupBinding = PortalLDAPUtil.getGroup(
076 ldapServerId, userGroup.getCompanyId(), userGroup.getName());
077
078 if (groupBinding != null) {
079 return PortalLDAPUtil.getNameInNamespace(
080 ldapServerId, userGroup.getCompanyId(), groupBinding);
081 }
082
083 StringBundler sb = new StringBundler(5);
084
085 sb.append(
086 GetterUtil.getString(
087 groupMappings.getProperty(_groupDNFieldName), _DEFAULT_DN));
088 sb.append(StringPool.EQUAL);
089 sb.append(userGroup.getName());
090 sb.append(StringPool.COMMA);
091 sb.append(
092 PortalLDAPUtil.getGroupsDN(ldapServerId, userGroup.getCompanyId()));
093
094 return sb.toString();
095 }
096
097 @Override
098 public Modifications getLDAPContactModifications(
099 Contact contact, Map<String, Serializable> contactExpandoAttributes,
100 Properties contactMappings, Properties contactExpandoMappings)
101 throws Exception {
102
103 if (contactMappings.isEmpty() && contactExpandoMappings.isEmpty()) {
104 return null;
105 }
106
107 Modifications modifications = getModifications(
108 contact, contactMappings, _reservedContactFieldNames);
109
110 populateCustomAttributeModifications(
111 contact, contact.getExpandoBridge(), contactExpandoAttributes,
112 contactExpandoMappings, modifications);
113
114 return modifications;
115 }
116
117 @Override
118 public Attributes getLDAPGroupAttributes(
119 long ldapServerId, UserGroup userGroup, User user,
120 Properties groupMappings, Properties userMappings)
121 throws Exception {
122
123 Attributes attributes = new BasicAttributes(true);
124
125 Attribute objectClass = new BasicAttribute(_OBJECT_CLASS);
126
127 String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
128
129 String[] defaultObjectClasses = PrefsPropsUtil.getStringArray(
130 userGroup.getCompanyId(),
131 PropsKeys.LDAP_GROUP_DEFAULT_OBJECT_CLASSES + postfix,
132 StringPool.COMMA);
133
134 for (int i = 0; i < defaultObjectClasses.length; i++) {
135 objectClass.add(defaultObjectClasses[i]);
136 }
137
138 attributes.put(objectClass);
139
140 addAttributeMapping(
141 groupMappings.getProperty(GroupConverterKeys.GROUP_NAME),
142 userGroup.getName(), attributes);
143 addAttributeMapping(
144 groupMappings.getProperty(GroupConverterKeys.DESCRIPTION),
145 userGroup.getDescription(), attributes);
146 addAttributeMapping(
147 groupMappings.getProperty(GroupConverterKeys.USER),
148 getUserDNName(ldapServerId, user, userMappings), attributes);
149
150 return attributes;
151 }
152
153 @Override
154 public Modifications getLDAPGroupModifications(
155 long ldapServerId, UserGroup userGroup, User user,
156 Properties groupMappings, Properties userMappings,
157 LDAPOperation ldapOperation)
158 throws Exception {
159
160 Modifications modifications = Modifications.getInstance();
161
162 String groupDN = getGroupDNName(ldapServerId, userGroup, groupMappings);
163 String userDN = getUserDNName(ldapServerId, user, userMappings);
164
165 if (PortalLDAPUtil.isGroupMember(
166 ldapServerId, user.getCompanyId(), groupDN, userDN)) {
167
168 if (ldapOperation == LDAPOperation.REMOVE) {
169 modifications.addItem(
170 DirContext.REMOVE_ATTRIBUTE,
171 groupMappings.getProperty(GroupConverterKeys.USER), userDN);
172 }
173 }
174 else {
175 if (ldapOperation == LDAPOperation.ADD) {
176 modifications.addItem(
177 DirContext.ADD_ATTRIBUTE,
178 groupMappings.getProperty(GroupConverterKeys.USER), userDN);
179 }
180 }
181
182 return modifications;
183 }
184
185 @Override
186 public Attributes getLDAPUserAttributes(
187 long ldapServerId, User user, Properties userMappings)
188 throws SystemException {
189
190 Attributes attributes = new BasicAttributes(true);
191
192 Attribute objectClass = new BasicAttribute(_OBJECT_CLASS);
193
194 String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
195
196 String[] defaultObjectClasses = PrefsPropsUtil.getStringArray(
197 user.getCompanyId(),
198 PropsKeys.LDAP_USER_DEFAULT_OBJECT_CLASSES + postfix,
199 StringPool.COMMA);
200
201 for (int i = 0; i < defaultObjectClasses.length; i++) {
202 objectClass.add(defaultObjectClasses[i]);
203 }
204
205 attributes.put(objectClass);
206
207 addAttributeMapping(
208 userMappings.getProperty(UserConverterKeys.UUID), user.getUuid(),
209 attributes);
210 addAttributeMapping(
211 userMappings.getProperty(UserConverterKeys.SCREEN_NAME),
212 user.getScreenName(), attributes);
213 addAttributeMapping(
214 userMappings.getProperty(UserConverterKeys.PASSWORD),
215 getEncryptedPasswordForLDAP(user, userMappings), attributes);
216 addAttributeMapping(
217 userMappings.getProperty(UserConverterKeys.EMAIL_ADDRESS),
218 user.getEmailAddress(), attributes);
219 addAttributeMapping(
220 userMappings.getProperty(UserConverterKeys.FULL_NAME),
221 user.getFullName(), attributes);
222 addAttributeMapping(
223 userMappings.getProperty(UserConverterKeys.FIRST_NAME),
224 user.getFirstName(), attributes);
225 addAttributeMapping(
226 userMappings.getProperty(UserConverterKeys.MIDDLE_NAME),
227 user.getMiddleName(), attributes);
228 addAttributeMapping(
229 userMappings.getProperty(UserConverterKeys.LAST_NAME),
230 user.getLastName(), attributes);
231 addAttributeMapping(
232 userMappings.getProperty(UserConverterKeys.JOB_TITLE),
233 user.getJobTitle(), attributes);
234 addAttributeMapping(
235 userMappings.getProperty(UserConverterKeys.PORTRAIT),
236 getUserPortrait(user), attributes);
237 addAttributeMapping(
238 userMappings.getProperty(UserConverterKeys.STATUS),
239 String.valueOf(user.getStatus()), attributes);
240
241 return attributes;
242 }
243
244 @Override
245 public Modifications getLDAPUserGroupModifications(
246 long ldapServerId, List<UserGroup> userGroups, User user,
247 Properties userMappings)
248 throws Exception {
249
250 Modifications modifications = Modifications.getInstance();
251
252 String groupMappingAttributeName = userMappings.getProperty(
253 UserConverterKeys.GROUP);
254
255 if (Validator.isNull(groupMappingAttributeName)) {
256 return modifications;
257 }
258
259 Properties groupMappings = LDAPSettingsUtil.getGroupMappings(
260 ldapServerId, user.getCompanyId());
261
262 String userDN = getUserDNName(ldapServerId, user, userMappings);
263
264 for (UserGroup userGroup : userGroups) {
265 String groupDN = getGroupDNName(
266 ldapServerId, userGroup, groupMappings);
267
268 if (PortalLDAPUtil.isUserGroupMember(
269 ldapServerId, user.getCompanyId(), groupDN, userDN)) {
270
271 continue;
272 }
273
274 modifications.addItem(
275 DirContext.ADD_ATTRIBUTE, groupMappingAttributeName, groupDN);
276 }
277
278 return modifications;
279 }
280
281 @Override
282 public Modifications getLDAPUserModifications(
283 User user, Map<String, Serializable> userExpandoAttributes,
284 Properties userMappings, Properties userExpandoMappings)
285 throws Exception {
286
287 Modifications modifications = getModifications(
288 user, userMappings, _reservedUserFieldNames);
289
290 if (user.isPasswordModified() &&
291 Validator.isNotNull(user.getPasswordUnencrypted())) {
292
293 String newPassword = getEncryptedPasswordForLDAP(
294 user, userMappings);
295
296 String passwordKey = userMappings.getProperty(
297 UserConverterKeys.PASSWORD);
298
299 addModificationItem(passwordKey, newPassword, modifications);
300 }
301
302 String portraitKey = userMappings.getProperty(
303 UserConverterKeys.PORTRAIT);
304
305 if (Validator.isNotNull(portraitKey)) {
306 addModificationItem(
307 new BasicAttribute(portraitKey, getUserPortrait(user)),
308 modifications);
309 }
310
311 populateCustomAttributeModifications(
312 user, user.getExpandoBridge(), userExpandoAttributes,
313 userExpandoMappings, modifications);
314
315 return modifications;
316 }
317
318 @Override
319 public String getUserDNName(
320 long ldapServerId, User user, Properties userMappings)
321 throws Exception {
322
323 Binding userBinding = PortalLDAPUtil.getUser(
324 ldapServerId, user.getCompanyId(), user.getScreenName(),
325 user.getEmailAddress());
326
327 if (userBinding != null) {
328 return PortalLDAPUtil.getNameInNamespace(
329 ldapServerId, user.getCompanyId(), userBinding);
330 }
331
332 StringBundler sb = new StringBundler(5);
333
334 sb.append(
335 GetterUtil.getString(
336 userMappings.getProperty(_userDNFieldName), _DEFAULT_DN));
337 sb.append(StringPool.EQUAL);
338 sb.append(PropertyUtils.getProperty(user, _userDNFieldName));
339 sb.append(StringPool.COMMA);
340 sb.append(PortalLDAPUtil.getUsersDN(ldapServerId, user.getCompanyId()));
341
342 return sb.toString();
343 }
344
345 public void setContactReservedFieldNames(
346 List<String> reservedContactFieldNames) {
347
348 for (String reservedContactFieldName : reservedContactFieldNames) {
349 _reservedContactFieldNames.put(
350 reservedContactFieldName, reservedContactFieldName);
351 }
352 }
353
354 public void setUserDNFieldName(String userDNFieldName) {
355 _userDNFieldName = userDNFieldName;
356 }
357
358 public void setUserReservedFieldNames(List<String> reservedUserFieldNames) {
359 for (String reservedUserFieldName : reservedUserFieldNames) {
360 _reservedUserFieldNames.put(
361 reservedUserFieldName, reservedUserFieldName);
362 }
363 }
364
365 protected void addAttributeMapping(
366 String attributeName, Object attributeValue, Attributes attributes) {
367
368 if (Validator.isNotNull(attributeName) && (attributeValue != null)) {
369 attributes.put(attributeName, attributeValue);
370 }
371 }
372
373 protected void addAttributeMapping(
374 String attributeName, String attributeValue, Attributes attributes) {
375
376 if (Validator.isNotNull(attributeName) &&
377 Validator.isNotNull(attributeValue)) {
378
379 attributes.put(attributeName, attributeValue);
380 }
381 }
382
383 protected void addModificationItem(
384 BasicAttribute basicAttribute, Modifications modifications) {
385
386 if (Validator.isNotNull(basicAttribute)) {
387 modifications.addItem(basicAttribute);
388 }
389 }
390
391 protected void addModificationItem(
392 String attributeName, String attributeValue,
393 Modifications modifications) {
394
395 if (Validator.isNotNull(attributeName)) {
396 modifications.addItem(attributeName, attributeValue);
397 }
398 }
399
400 protected String getEncryptedPasswordForLDAP(
401 User user, Properties userMappings)
402 throws SystemException {
403
404 String password = user.getPasswordUnencrypted();
405
406 if (Validator.isNull(password)) {
407 return password;
408 }
409
410 String algorithm = PrefsPropsUtil.getString(
411 user.getCompanyId(),
412 PropsKeys.LDAP_AUTH_PASSWORD_ENCRYPTION_ALGORITHM);
413
414 if (Validator.isNull(algorithm)) {
415 return password;
416 }
417
418 try {
419 StringBundler sb = new StringBundler(4);
420
421 if (!algorithm.equals(PasswordEncryptorUtil.TYPE_NONE)) {
422 sb.append(StringPool.OPEN_CURLY_BRACE);
423 sb.append(algorithm);
424 sb.append(StringPool.CLOSE_CURLY_BRACE);
425 }
426
427 sb.append(PasswordEncryptorUtil.encrypt(algorithm, password, null));
428
429 String passwordKey = userMappings.getProperty(
430 UserConverterKeys.PASSWORD);
431
432 if (passwordKey.equals("unicodePwd")) {
433 String quotedPassword = StringPool.QUOTE.concat(
434 sb.toString()).concat(StringPool.QUOTE);
435
436 byte[] unicodePassword = quotedPassword.getBytes("UTF-16LE");
437
438 return new String(unicodePassword);
439 }
440
441 return sb.toString();
442 }
443 catch (Exception e) {
444 throw new SystemException(e);
445 }
446 }
447
448 protected Modifications getModifications(
449 Object object, Properties objectMappings,
450 Map<String, String> reservedFieldNames) {
451
452 Modifications modifications = Modifications.getInstance();
453
454 for (Map.Entry<Object, Object> entry : objectMappings.entrySet()) {
455 String fieldName = (String)entry.getKey();
456
457 if (reservedFieldNames.containsKey(fieldName)) {
458 continue;
459 }
460
461 String ldapAttributeName = (String)entry.getValue();
462
463 try {
464 Object attributeValue = PropertyUtils.getProperty(
465 object, fieldName);
466
467 if (attributeValue != null) {
468 addModificationItem(
469 ldapAttributeName, attributeValue.toString(),
470 modifications);
471 }
472 }
473 catch (Exception e) {
474 if (_log.isWarnEnabled()) {
475 _log.warn(
476 "Unable to map field " + fieldName + " to class " +
477 object.getClass(),
478 e);
479 }
480 }
481 }
482
483 return modifications;
484 }
485
486 protected byte[] getUserPortrait(User user) {
487 byte[] bytes = null;
488
489 if (user.getPortraitId() == 0) {
490 return bytes;
491 }
492
493 Image image = null;
494
495 try {
496 image = ImageLocalServiceUtil.getImage(user.getPortraitId());
497
498 if (image != null) {
499 bytes = image.getTextObj();
500 }
501 }
502 catch (Exception e) {
503 if (_log.isWarnEnabled()) {
504 _log.warn(
505 "Unable to get the portrait for user " + user.getUserId(),
506 e);
507 }
508 }
509
510 return bytes;
511 }
512
513 protected void populateCustomAttributeModifications(
514 Object object, ExpandoBridge expandoBridge,
515 Map<String, Serializable> expandoAttributes, Properties expandoMappings,
516 Modifications modifications) {
517
518 if ((expandoAttributes == null) || expandoAttributes.isEmpty()) {
519 return;
520 }
521
522 for (Map.Entry<Object, Object> entry : expandoMappings.entrySet()) {
523 String fieldName = (String)entry.getKey();
524 String ldapAttributeName = (String)entry.getValue();
525
526 Serializable fieldValue = expandoAttributes.get(fieldName);
527
528 if (fieldValue == null) {
529 continue;
530 }
531
532 try {
533 int type = expandoBridge.getAttributeType(fieldName);
534
535 String value = ExpandoConverterUtil.getStringFromAttribute(
536 type, fieldValue);
537
538 addModificationItem(ldapAttributeName, value, modifications);
539 }
540 catch (Exception e) {
541 if (_log.isWarnEnabled()) {
542 _log.warn(
543 "Unable to map field " + fieldName + " to class " +
544 object.getClass(),
545 e);
546 }
547 }
548 }
549 }
550
551 private static final String _DEFAULT_DN = "cn";
552
553 private static final String _OBJECT_CLASS = "objectclass";
554
555 private static Log _log = LogFactoryUtil.getLog(
556 DefaultPortalToLDAPConverter.class);
557
558 private String _groupDNFieldName = GroupConverterKeys.GROUP_NAME;
559 private Map<String, String> _reservedContactFieldNames =
560 new HashMap<String, String>();
561 private Map<String, String> _reservedUserFieldNames =
562 new HashMap<String, String>();
563 private String _userDNFieldName = UserConverterKeys.SCREEN_NAME;
564
565 }