001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
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.service.ImageLocalServiceUtil;
030    import com.liferay.portal.util.PrefsPropsUtil;
031    import com.liferay.portlet.expando.model.ExpandoBridge;
032    import com.liferay.portlet.expando.util.ExpandoConverterUtil;
033    
034    import java.io.Serializable;
035    
036    import java.util.HashMap;
037    import java.util.List;
038    import java.util.Map;
039    import java.util.Properties;
040    
041    import javax.naming.Binding;
042    import javax.naming.directory.Attribute;
043    import javax.naming.directory.Attributes;
044    import javax.naming.directory.BasicAttribute;
045    import javax.naming.directory.BasicAttributes;
046    import javax.naming.directory.DirContext;
047    
048    import org.apache.commons.beanutils.PropertyUtils;
049    
050    /**
051     * @author Michael C. Han
052     * @author Brian Wing Shun Chan
053     * @author Marcellus Tavares
054     * @author Wesley Gong
055     */
056    public class BasePortalToLDAPConverter implements PortalToLDAPConverter {
057    
058            public BasePortalToLDAPConverter() {
059                    _reservedUserFieldNames.put(
060                            UserConverterKeys.GROUP, UserConverterKeys.GROUP);
061                    _reservedUserFieldNames.put(
062                            UserConverterKeys.PASSWORD, UserConverterKeys.PASSWORD);
063                    _reservedUserFieldNames.put(
064                            UserConverterKeys.PORTRAIT, UserConverterKeys.PORTRAIT);
065                    _reservedUserFieldNames.put(
066                            UserConverterKeys.SCREEN_NAME, UserConverterKeys.SCREEN_NAME);
067            }
068    
069            public String getGroupDNName(
070                            long ldapServerId, UserGroup userGroup, Properties groupMappings)
071                    throws Exception {
072    
073                    Binding groupBinding = PortalLDAPUtil.getGroup(
074                            ldapServerId, userGroup.getCompanyId(), userGroup.getName());
075    
076                    if (groupBinding != null) {
077                            return PortalLDAPUtil.getNameInNamespace(
078                                    ldapServerId, userGroup.getCompanyId(), groupBinding);
079                    }
080    
081                    StringBundler sb = new StringBundler(5);
082    
083                    sb.append(
084                            GetterUtil.getString(
085                                    groupMappings.getProperty(_groupDNFieldName), _DEFAULT_DN));
086                    sb.append(StringPool.EQUAL);
087                    sb.append(userGroup.getName());
088                    sb.append(StringPool.COMMA);
089                    sb.append(
090                            PortalLDAPUtil.getGroupsDN(
091                                    ldapServerId, userGroup.getCompanyId()));
092    
093                    return sb.toString();
094            }
095    
096            public Modifications getLDAPContactModifications(
097                            Contact contact, Map<String, Serializable> contactExpandoAttributes,
098                            Properties contactMappings, Properties contactExpandoMappings)
099                    throws Exception {
100    
101                    if (contactMappings.isEmpty() && contactExpandoMappings.isEmpty()) {
102                            return null;
103                    }
104    
105                    Modifications modifications = getModifications(
106                            contact, contactMappings, _reservedContactFieldNames);
107    
108                    populateCustomAttributeModifications(
109                            contact, contact.getExpandoBridge(), contactExpandoAttributes,
110                            contactExpandoMappings, modifications);
111    
112                    return modifications;
113            }
114    
115            public Attributes getLDAPGroupAttributes(
116                            long ldapServerId, UserGroup userGroup, User user,
117                            Properties groupMappings, Properties userMappings)
118                    throws Exception {
119    
120                    Attributes attributes = new BasicAttributes(true);
121    
122                    Attribute objectClass = new BasicAttribute(_OBJECT_CLASS);
123    
124                    String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
125    
126                    String[] defaultObjectClasses = PrefsPropsUtil.getStringArray(
127                            userGroup.getCompanyId(),
128                            PropsKeys.LDAP_GROUP_DEFAULT_OBJECT_CLASSES + postfix,
129                            StringPool.COMMA);
130    
131                    for (int i = 0; i < defaultObjectClasses.length; i++) {
132                            objectClass.add(defaultObjectClasses[i]);
133                    }
134    
135                    attributes.put(objectClass);
136    
137                    addAttributeMapping(
138                            groupMappings.getProperty(GroupConverterKeys.GROUP_NAME),
139                            userGroup.getName(), attributes);
140                    addAttributeMapping(
141                            groupMappings.getProperty(GroupConverterKeys.DESCRIPTION),
142                            userGroup.getDescription(), attributes);
143                    addAttributeMapping(
144                            groupMappings.getProperty(GroupConverterKeys.USER),
145                            getUserDNName(ldapServerId, user, userMappings), attributes);
146    
147                    return attributes;
148            }
149    
150            public Modifications getLDAPGroupModifications(
151                            long ldapServerId, UserGroup userGroup, User user,
152                            Properties groupMappings, Properties userMappings)
153                    throws Exception {
154    
155                    Modifications modifications = Modifications.getInstance();
156    
157                    String groupDN = getGroupDNName(ldapServerId, userGroup, groupMappings);
158                    String userDN = getUserDNName(ldapServerId, user, userMappings);
159    
160                    if (!PortalLDAPUtil.isGroupMember(
161                                    ldapServerId, user.getCompanyId(), groupDN, userDN)) {
162    
163                            modifications.addItem(
164                                    DirContext.ADD_ATTRIBUTE,
165                                    groupMappings.getProperty(GroupConverterKeys.USER), userDN);
166                    }
167    
168                    return modifications;
169            }
170    
171            public Attributes getLDAPUserAttributes(
172                            long ldapServerId, User user, Properties userMappings)
173                    throws SystemException {
174    
175                    Attributes attributes = new BasicAttributes(true);
176    
177                    Attribute objectClass = new BasicAttribute(_OBJECT_CLASS);
178    
179                    String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
180    
181                    String[] defaultObjectClasses = PrefsPropsUtil.getStringArray(
182                            user.getCompanyId(),
183                            PropsKeys.LDAP_USER_DEFAULT_OBJECT_CLASSES + postfix,
184                            StringPool.COMMA);
185    
186                    for (int i = 0; i < defaultObjectClasses.length; i++) {
187                            objectClass.add(defaultObjectClasses[i]);
188                    }
189    
190                    attributes.put(objectClass);
191    
192                    addAttributeMapping(
193                            userMappings.getProperty(UserConverterKeys.SCREEN_NAME),
194                            user.getScreenName(), attributes);
195                    addAttributeMapping(
196                            userMappings.getProperty(UserConverterKeys.PASSWORD),
197                            user.getPasswordUnencrypted(), attributes);
198                    addAttributeMapping(
199                            userMappings.getProperty(UserConverterKeys.EMAIL_ADDRESS),
200                            user.getEmailAddress(), attributes);
201                    addAttributeMapping(
202                            userMappings.getProperty(UserConverterKeys.FULL_NAME),
203                            user.getFullName(), attributes);
204                    addAttributeMapping(
205                            userMappings.getProperty(UserConverterKeys.FIRST_NAME),
206                            user.getFirstName(), attributes);
207                    addAttributeMapping(
208                            userMappings.getProperty(UserConverterKeys.MIDDLE_NAME),
209                            user.getMiddleName(), attributes);
210                    addAttributeMapping(
211                            userMappings.getProperty(UserConverterKeys.LAST_NAME),
212                            user.getLastName(), attributes);
213                    addAttributeMapping(
214                            userMappings.getProperty(UserConverterKeys.JOB_TITLE),
215                            user.getJobTitle(), attributes);
216                    addAttributeMapping(
217                            userMappings.getProperty(UserConverterKeys.PORTRAIT),
218                            getUserPortrait(user), attributes);
219    
220                    return attributes;
221            }
222    
223            public Modifications getLDAPUserGroupModifications(
224                            long ldapServerId, List<UserGroup> userGroups, User user,
225                            Properties userMappings)
226                    throws Exception {
227    
228                    Modifications modifications = Modifications.getInstance();
229    
230                    Properties groupMappings = LDAPSettingsUtil.getGroupMappings(
231                            ldapServerId, user.getCompanyId());
232    
233                    String userDN = getUserDNName(ldapServerId, user, userMappings);
234    
235                    for (UserGroup userGroup : userGroups) {
236                            String groupDN = getGroupDNName(
237                                    ldapServerId, userGroup, groupMappings);
238    
239                            if (PortalLDAPUtil.isUserGroupMember(
240                                            ldapServerId, user.getCompanyId(), groupDN, userDN)) {
241    
242                                    continue;
243                            }
244    
245                            modifications.addItem(
246                                    DirContext.ADD_ATTRIBUTE,
247                                    userMappings.getProperty(UserConverterKeys.GROUP), groupDN);
248                    }
249    
250                    return modifications;
251            }
252    
253            public Modifications getLDAPUserModifications(
254                            User user, Map<String, Serializable> userExpandoAttributes,
255                            Properties userMappings, Properties userExpandoMappings)
256                    throws Exception {
257    
258                    Modifications modifications = getModifications(
259                            user, userMappings, _reservedUserFieldNames);
260    
261                    if (user.isPasswordModified() &&
262                            Validator.isNotNull(user.getPasswordUnencrypted())) {
263    
264                            String newPassword = user.getPasswordUnencrypted();
265    
266                            String passwordKey = userMappings.getProperty(
267                                    UserConverterKeys.PASSWORD);
268    
269                            if (passwordKey.equals("unicodePwd")) {
270                                    String newQuotedPassword = StringPool.QUOTE.concat(
271                                            newPassword).concat(StringPool.QUOTE);
272    
273                                    byte[] newUnicodePassword = newQuotedPassword.getBytes(
274                                            "UTF-16LE");
275    
276                                    addModificationItem(
277                                            new BasicAttribute(passwordKey, newUnicodePassword),
278                                            modifications);
279                            }
280                            else {
281                                    addModificationItem(passwordKey, newPassword, modifications);
282                            }
283                    }
284    
285                    String portraitKey = userMappings.getProperty(
286                            UserConverterKeys.PORTRAIT);
287    
288                    addModificationItem(
289                            new BasicAttribute(portraitKey, getUserPortrait(user)),
290                            modifications);
291    
292                    populateCustomAttributeModifications(
293                            user, user.getExpandoBridge(), userExpandoAttributes,
294                            userExpandoMappings, modifications);
295    
296                    return modifications;
297            }
298    
299            public String getUserDNName(
300                            long ldapServerId, User user, Properties userMappings)
301                    throws Exception {
302    
303                    Binding userBinding = PortalLDAPUtil.getUser(
304                            ldapServerId, user.getCompanyId(), user.getScreenName(),
305                            user.getEmailAddress());
306    
307                    if (userBinding != null) {
308                            return PortalLDAPUtil.getNameInNamespace(
309                                    ldapServerId, user.getCompanyId(), userBinding);
310                    }
311    
312                    StringBundler sb = new StringBundler(5);
313    
314                    sb.append(
315                            GetterUtil.getString(
316                                    userMappings.getProperty(_userDNFieldName), _DEFAULT_DN));
317                    sb.append(StringPool.EQUAL);
318                    sb.append(PropertyUtils.getProperty(user, _userDNFieldName));
319                    sb.append(StringPool.COMMA);
320                    sb.append(PortalLDAPUtil.getUsersDN(ldapServerId, user.getCompanyId()));
321    
322                    return sb.toString();
323            }
324    
325            public void setContactReservedFieldNames(
326                    List<String> reservedContactFieldNames) {
327    
328                    for (String reservedContactFieldName : reservedContactFieldNames) {
329                            _reservedContactFieldNames.put(
330                                    reservedContactFieldName, reservedContactFieldName);
331                    }
332            }
333    
334            public void setUserDNFieldName(String userDNFieldName) {
335                    _userDNFieldName = userDNFieldName;
336            }
337    
338            public void setUserReservedFieldNames(List<String> reservedUserFieldNames) {
339                    for (String reservedUserFieldName : reservedUserFieldNames) {
340                            _reservedUserFieldNames.put(
341                                    reservedUserFieldName, reservedUserFieldName);
342                    }
343            }
344    
345            protected void addAttributeMapping(
346                    String attributeName, Object attributeValue, Attributes attributes) {
347    
348                    if (Validator.isNotNull(attributeName) && (attributeValue != null)) {
349                            attributes.put(attributeName, attributeValue);
350                    }
351            }
352    
353            protected void addAttributeMapping(
354                    String attributeName, String attributeValue, Attributes attributes) {
355    
356                    if (Validator.isNotNull(attributeName) &&
357                            Validator.isNotNull(attributeValue)) {
358    
359                            attributes.put(attributeName, attributeValue);
360                    }
361            }
362    
363            protected void addModificationItem(
364                    BasicAttribute basicAttribute, Modifications modifications) {
365    
366                    if (Validator.isNotNull(basicAttribute)) {
367                            modifications.addItem(basicAttribute);
368                    }
369            }
370    
371            protected void addModificationItem(
372                    String attributeName, String attributeValue,
373                    Modifications modifications) {
374    
375                    if (Validator.isNotNull(attributeName) &&
376                            Validator.isNotNull(attributeValue)) {
377    
378                            modifications.addItem(attributeName, attributeValue);
379                    }
380            }
381    
382            protected Modifications getModifications(
383                    Object object, Properties objectMappings,
384                    Map<String, String> reservedFieldNames) {
385    
386                    Modifications modifications = Modifications.getInstance();
387    
388                    for (Map.Entry<Object, Object> entry : objectMappings.entrySet()) {
389                            String fieldName = (String)entry.getKey();
390    
391                            if (reservedFieldNames.containsKey(fieldName)) {
392                                    continue;
393                            }
394    
395                            String ldapAttributeName = (String)entry.getValue();
396    
397                            try {
398                                    Object attributeValue = PropertyUtils.getProperty(
399                                            object, fieldName);
400    
401                                    if (attributeValue != null) {
402                                            addModificationItem(
403                                                    ldapAttributeName, attributeValue.toString(),
404                                                    modifications);
405                                    }
406                            }
407                            catch (Exception e) {
408                                    if (_log.isWarnEnabled()) {
409                                            _log.warn(
410                                                    "Unable to map field " + fieldName + " to class " +
411                                                            object.getClass(),
412                                                    e);
413                                    }
414                            }
415                    }
416    
417                    return modifications;
418            }
419    
420            protected byte[] getUserPortrait(User user) {
421                    byte[] bytes = null;
422    
423                    if (user.getPortraitId() == 0) {
424                            return bytes;
425                    }
426    
427                    Image image = null;
428    
429                    try {
430                            image = ImageLocalServiceUtil.getImage(user.getPortraitId());
431    
432                            if (image != null) {
433                                    bytes = image.getTextObj();
434                            }
435                    }
436                    catch (Exception e) {
437                            if (_log.isWarnEnabled()) {
438                                    _log.warn(
439                                            "Unable to get the portrait for user " + user.getUserId(),
440                                            e);
441                            }
442                    }
443    
444                    return bytes;
445            }
446    
447            protected void populateCustomAttributeModifications(
448                    Object object, ExpandoBridge expandoBridge,
449                    Map<String, Serializable> expandoAttributes,
450                    Properties expandoMappings, Modifications modifications) {
451    
452                    if ((expandoAttributes == null) || expandoAttributes.isEmpty()) {
453                            return;
454                    }
455    
456                    for (Map.Entry<Object, Object> entry : expandoMappings.entrySet()) {
457                            String fieldName = (String)entry.getKey();
458                            String ldapAttributeName = (String)entry.getValue();
459    
460                            Serializable fieldValue = expandoAttributes.get(fieldName);
461    
462                            if (fieldValue == null) {
463                                    continue;
464                            }
465    
466                            try {
467                                    int type = expandoBridge.getAttributeType(fieldName);
468    
469                                    String value = ExpandoConverterUtil.getStringFromAttribute(
470                                            type, fieldValue);
471    
472                                    addModificationItem(ldapAttributeName, value, modifications);
473                            }
474                            catch (Exception e) {
475                                    if (_log.isWarnEnabled()) {
476                                            _log.warn(
477                                                    "Unable to map field " + fieldName + " to class " +
478                                                            object.getClass(),
479                                                    e);
480                                    }
481                            }
482                    }
483            }
484    
485            private static final String _DEFAULT_DN = "cn";
486    
487            private static final String _OBJECT_CLASS = "objectclass";
488    
489            private static Log _log = LogFactoryUtil.getLog(
490                    BasePortalToLDAPConverter.class);
491    
492            private Map<String, String> _reservedContactFieldNames =
493                    new HashMap<String, String>();
494            private Map<String, String> _reservedUserFieldNames =
495                    new HashMap<String, String>();
496    
497            private String _groupDNFieldName = GroupConverterKeys.GROUP_NAME;
498            private String _userDNFieldName = UserConverterKeys.SCREEN_NAME;
499    
500    }