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.pwd.PasswordEncryptorUtil;
031 import com.liferay.portal.service.ImageLocalServiceUtil;
032 import com.liferay.portal.util.PrefsPropsUtil;
033 import com.liferay.portlet.expando.model.ExpandoBridge;
034 import com.liferay.portlet.expando.util.ExpandoConverterUtil;
035
036 import java.io.Serializable;
037
038 import java.util.HashMap;
039 import java.util.List;
040 import java.util.Map;
041 import java.util.Properties;
042
043 import javax.naming.Binding;
044 import javax.naming.directory.Attribute;
045 import javax.naming.directory.Attributes;
046 import javax.naming.directory.BasicAttribute;
047 import javax.naming.directory.BasicAttributes;
048 import javax.naming.directory.DirContext;
049
050 import org.apache.commons.beanutils.PropertyUtils;
051
052
058 public class DefaultPortalToLDAPConverter implements PortalToLDAPConverter {
059
060 public DefaultPortalToLDAPConverter() {
061 _reservedUserFieldNames.put(
062 UserConverterKeys.GROUP, UserConverterKeys.GROUP);
063 _reservedUserFieldNames.put(
064 UserConverterKeys.PASSWORD, UserConverterKeys.PASSWORD);
065 _reservedUserFieldNames.put(
066 UserConverterKeys.PORTRAIT, UserConverterKeys.PORTRAIT);
067 _reservedUserFieldNames.put(
068 UserConverterKeys.SCREEN_NAME, UserConverterKeys.SCREEN_NAME);
069 }
070
071 @Override
072 public String getGroupDNName(
073 long ldapServerId, UserGroup userGroup, Properties groupMappings)
074 throws Exception {
075
076 Binding groupBinding = PortalLDAPUtil.getGroup(
077 ldapServerId, userGroup.getCompanyId(), userGroup.getName());
078
079 if (groupBinding != null) {
080 return PortalLDAPUtil.getNameInNamespace(
081 ldapServerId, userGroup.getCompanyId(), groupBinding);
082 }
083
084 StringBundler sb = new StringBundler(5);
085
086 sb.append(
087 GetterUtil.getString(
088 groupMappings.getProperty(_groupDNFieldName), _DEFAULT_DN));
089 sb.append(StringPool.EQUAL);
090 sb.append(userGroup.getName());
091 sb.append(StringPool.COMMA);
092 sb.append(
093 PortalLDAPUtil.getGroupsDN(ldapServerId, userGroup.getCompanyId()));
094
095 return sb.toString();
096 }
097
098 @Override
099 public Modifications getLDAPContactModifications(
100 Contact contact, Map<String, Serializable> contactExpandoAttributes,
101 Properties contactMappings, Properties contactExpandoMappings)
102 throws Exception {
103
104 if (contactMappings.isEmpty() && contactExpandoMappings.isEmpty()) {
105 return null;
106 }
107
108 Modifications modifications = getModifications(
109 contact, contactMappings, _reservedContactFieldNames);
110
111 populateCustomAttributeModifications(
112 contact, contact.getExpandoBridge(), contactExpandoAttributes,
113 contactExpandoMappings, modifications);
114
115 return modifications;
116 }
117
118 @Override
119 public Attributes getLDAPGroupAttributes(
120 long ldapServerId, UserGroup userGroup, User user,
121 Properties groupMappings, Properties userMappings)
122 throws Exception {
123
124 Attributes attributes = new BasicAttributes(true);
125
126 Attribute objectClass = new BasicAttribute(_OBJECT_CLASS);
127
128 String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
129
130 String[] defaultObjectClasses = PrefsPropsUtil.getStringArray(
131 userGroup.getCompanyId(),
132 PropsKeys.LDAP_GROUP_DEFAULT_OBJECT_CLASSES + postfix,
133 StringPool.COMMA);
134
135 for (int i = 0; i < defaultObjectClasses.length; i++) {
136 objectClass.add(defaultObjectClasses[i]);
137 }
138
139 attributes.put(objectClass);
140
141 addAttributeMapping(
142 groupMappings.getProperty(GroupConverterKeys.GROUP_NAME),
143 userGroup.getName(), attributes);
144 addAttributeMapping(
145 groupMappings.getProperty(GroupConverterKeys.DESCRIPTION),
146 userGroup.getDescription(), attributes);
147 addAttributeMapping(
148 groupMappings.getProperty(GroupConverterKeys.USER),
149 getUserDNName(ldapServerId, user, userMappings), attributes);
150
151 return attributes;
152 }
153
154 @Override
155 public Modifications getLDAPGroupModifications(
156 long ldapServerId, UserGroup userGroup, User user,
157 Properties groupMappings, Properties userMappings,
158 LDAPOperation ldapOperation)
159 throws Exception {
160
161 Modifications modifications = Modifications.getInstance();
162
163 String groupDN = getGroupDNName(ldapServerId, userGroup, groupMappings);
164 String userDN = getUserDNName(ldapServerId, user, userMappings);
165
166 if (PortalLDAPUtil.isGroupMember(
167 ldapServerId, user.getCompanyId(), groupDN, userDN)) {
168
169 if (ldapOperation == LDAPOperation.REMOVE) {
170 modifications.addItem(
171 DirContext.REMOVE_ATTRIBUTE,
172 groupMappings.getProperty(GroupConverterKeys.USER), userDN);
173 }
174 }
175 else {
176 if (ldapOperation == LDAPOperation.ADD) {
177 modifications.addItem(
178 DirContext.ADD_ATTRIBUTE,
179 groupMappings.getProperty(GroupConverterKeys.USER), userDN);
180 }
181 }
182
183 return modifications;
184 }
185
186 @Override
187 public Attributes getLDAPUserAttributes(
188 long ldapServerId, User user, Properties userMappings)
189 throws SystemException {
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 (Validator.isNotNull(basicAttribute)) {
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 throws SystemException {
415
416 String password = user.getPasswordUnencrypted();
417
418 if (Validator.isNull(password)) {
419 return password;
420 }
421
422 String algorithm = PrefsPropsUtil.getString(
423 user.getCompanyId(),
424 PropsKeys.LDAP_AUTH_PASSWORD_ENCRYPTION_ALGORITHM);
425
426 if (Validator.isNull(algorithm)) {
427 return password;
428 }
429
430 try {
431 StringBundler sb = new StringBundler(4);
432
433 sb.append(StringPool.OPEN_CURLY_BRACE);
434 sb.append(algorithm);
435 sb.append(StringPool.CLOSE_CURLY_BRACE);
436 sb.append(PasswordEncryptorUtil.encrypt(algorithm, password, null));
437
438 return sb.toString();
439 }
440 catch (PwdEncryptorException pee) {
441 throw new SystemException(pee);
442 }
443 }
444
445 protected Modifications getModifications(
446 Object object, Properties objectMappings,
447 Map<String, String> reservedFieldNames) {
448
449 Modifications modifications = Modifications.getInstance();
450
451 for (Map.Entry<Object, Object> entry : objectMappings.entrySet()) {
452 String fieldName = (String)entry.getKey();
453
454 if (reservedFieldNames.containsKey(fieldName)) {
455 continue;
456 }
457
458 String ldapAttributeName = (String)entry.getValue();
459
460 try {
461 Object attributeValue = PropertyUtils.getProperty(
462 object, fieldName);
463
464 if (attributeValue != null) {
465 addModificationItem(
466 ldapAttributeName, attributeValue.toString(),
467 modifications);
468 }
469 }
470 catch (Exception e) {
471 if (_log.isWarnEnabled()) {
472 _log.warn(
473 "Unable to map field " + fieldName + " to class " +
474 object.getClass(),
475 e);
476 }
477 }
478 }
479
480 return modifications;
481 }
482
483 protected byte[] getUserPortrait(User user) {
484 byte[] bytes = null;
485
486 if (user.getPortraitId() == 0) {
487 return bytes;
488 }
489
490 Image image = null;
491
492 try {
493 image = ImageLocalServiceUtil.getImage(user.getPortraitId());
494
495 if (image != null) {
496 bytes = image.getTextObj();
497 }
498 }
499 catch (Exception e) {
500 if (_log.isWarnEnabled()) {
501 _log.warn(
502 "Unable to get the portrait for user " + user.getUserId(),
503 e);
504 }
505 }
506
507 return bytes;
508 }
509
510 protected void populateCustomAttributeModifications(
511 Object object, ExpandoBridge expandoBridge,
512 Map<String, Serializable> expandoAttributes, Properties expandoMappings,
513 Modifications modifications) {
514
515 if ((expandoAttributes == null) || expandoAttributes.isEmpty()) {
516 return;
517 }
518
519 for (Map.Entry<Object, Object> entry : expandoMappings.entrySet()) {
520 String fieldName = (String)entry.getKey();
521 String ldapAttributeName = (String)entry.getValue();
522
523 Serializable fieldValue = expandoAttributes.get(fieldName);
524
525 if (fieldValue == null) {
526 continue;
527 }
528
529 try {
530 int type = expandoBridge.getAttributeType(fieldName);
531
532 String value = ExpandoConverterUtil.getStringFromAttribute(
533 type, fieldValue);
534
535 addModificationItem(ldapAttributeName, value, modifications);
536 }
537 catch (Exception e) {
538 if (_log.isWarnEnabled()) {
539 _log.warn(
540 "Unable to map field " + fieldName + " to class " +
541 object.getClass(),
542 e);
543 }
544 }
545 }
546 }
547
548 private static final String _DEFAULT_DN = "cn";
549
550 private static final String _OBJECT_CLASS = "objectclass";
551
552 private static Log _log = LogFactoryUtil.getLog(
553 DefaultPortalToLDAPConverter.class);
554
555 private String _groupDNFieldName = GroupConverterKeys.GROUP_NAME;
556 private Map<String, String> _reservedContactFieldNames =
557 new HashMap<String, String>();
558 private Map<String, String> _reservedUserFieldNames =
559 new HashMap<String, String>();
560 private String _userDNFieldName = UserConverterKeys.SCREEN_NAME;
561
562 }