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
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), 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(user);
294
295 String passwordKey = userMappings.getProperty(
296 UserConverterKeys.PASSWORD);
297
298 if (passwordKey.equals("unicodePwd")) {
299 String newQuotedPassword = StringPool.QUOTE.concat(
300 newPassword).concat(StringPool.QUOTE);
301
302 byte[] newUnicodePassword = newQuotedPassword.getBytes(
303 "UTF-16LE");
304
305 addModificationItem(
306 new BasicAttribute(passwordKey, newUnicodePassword),
307 modifications);
308 }
309 else {
310 addModificationItem(passwordKey, newPassword, modifications);
311 }
312 }
313
314 String portraitKey = userMappings.getProperty(
315 UserConverterKeys.PORTRAIT);
316
317 if (Validator.isNotNull(portraitKey)) {
318 addModificationItem(
319 new BasicAttribute(portraitKey, getUserPortrait(user)),
320 modifications);
321 }
322
323 populateCustomAttributeModifications(
324 user, user.getExpandoBridge(), userExpandoAttributes,
325 userExpandoMappings, modifications);
326
327 return modifications;
328 }
329
330 @Override
331 public String getUserDNName(
332 long ldapServerId, User user, Properties userMappings)
333 throws Exception {
334
335 Binding userBinding = PortalLDAPUtil.getUser(
336 ldapServerId, user.getCompanyId(), user.getScreenName(),
337 user.getEmailAddress());
338
339 if (userBinding != null) {
340 return PortalLDAPUtil.getNameInNamespace(
341 ldapServerId, user.getCompanyId(), userBinding);
342 }
343
344 StringBundler sb = new StringBundler(5);
345
346 sb.append(
347 GetterUtil.getString(
348 userMappings.getProperty(_userDNFieldName), _DEFAULT_DN));
349 sb.append(StringPool.EQUAL);
350 sb.append(PropertyUtils.getProperty(user, _userDNFieldName));
351 sb.append(StringPool.COMMA);
352 sb.append(PortalLDAPUtil.getUsersDN(ldapServerId, user.getCompanyId()));
353
354 return sb.toString();
355 }
356
357 public void setContactReservedFieldNames(
358 List<String> reservedContactFieldNames) {
359
360 for (String reservedContactFieldName : reservedContactFieldNames) {
361 _reservedContactFieldNames.put(
362 reservedContactFieldName, reservedContactFieldName);
363 }
364 }
365
366 public void setUserDNFieldName(String userDNFieldName) {
367 _userDNFieldName = userDNFieldName;
368 }
369
370 public void setUserReservedFieldNames(List<String> reservedUserFieldNames) {
371 for (String reservedUserFieldName : reservedUserFieldNames) {
372 _reservedUserFieldNames.put(
373 reservedUserFieldName, reservedUserFieldName);
374 }
375 }
376
377 protected void addAttributeMapping(
378 String attributeName, Object attributeValue, Attributes attributes) {
379
380 if (Validator.isNotNull(attributeName) && (attributeValue != null)) {
381 attributes.put(attributeName, attributeValue);
382 }
383 }
384
385 protected void addAttributeMapping(
386 String attributeName, String attributeValue, Attributes attributes) {
387
388 if (Validator.isNotNull(attributeName) &&
389 Validator.isNotNull(attributeValue)) {
390
391 attributes.put(attributeName, attributeValue);
392 }
393 }
394
395 protected void addModificationItem(
396 BasicAttribute basicAttribute, Modifications modifications) {
397
398 if (basicAttribute != null) {
399 modifications.addItem(basicAttribute);
400 }
401 }
402
403 protected void addModificationItem(
404 String attributeName, String attributeValue,
405 Modifications modifications) {
406
407 if (Validator.isNotNull(attributeName)) {
408 modifications.addItem(attributeName, attributeValue);
409 }
410 }
411
412 protected String getEncryptedPasswordForLDAP(User user) {
413 String password = user.getPasswordUnencrypted();
414
415 if (Validator.isNull(password)) {
416 return password;
417 }
418
419 String algorithm = PrefsPropsUtil.getString(
420 user.getCompanyId(),
421 PropsKeys.LDAP_AUTH_PASSWORD_ENCRYPTION_ALGORITHM);
422
423 if (Validator.isNull(algorithm)) {
424 return password;
425 }
426
427 try {
428 StringBundler sb = new StringBundler(4);
429
430 if (!algorithm.equals(PasswordEncryptorUtil.TYPE_NONE)) {
431 sb.append(StringPool.OPEN_CURLY_BRACE);
432 sb.append(algorithm);
433 sb.append(StringPool.CLOSE_CURLY_BRACE);
434 }
435
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 }