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