001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.security.ldap;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.security.pacl.DoPrivileged;
020    import com.liferay.portal.kernel.util.PropsKeys;
021    import com.liferay.portal.kernel.workflow.WorkflowConstants;
022    import com.liferay.portal.model.Contact;
023    import com.liferay.portal.model.User;
024    import com.liferay.portal.model.UserGroup;
025    import com.liferay.portal.service.UserGroupLocalServiceUtil;
026    import com.liferay.portal.service.UserLocalServiceUtil;
027    import com.liferay.portal.util.PrefsPropsUtil;
028    import com.liferay.portal.util.PropsValues;
029    
030    import java.io.Serializable;
031    
032    import java.util.List;
033    import java.util.Map;
034    import java.util.Properties;
035    
036    import javax.naming.Binding;
037    import javax.naming.CompositeName;
038    import javax.naming.Name;
039    import javax.naming.NameNotFoundException;
040    import javax.naming.directory.Attribute;
041    import javax.naming.directory.Attributes;
042    import javax.naming.directory.ModificationItem;
043    import javax.naming.directory.SchemaViolationException;
044    import javax.naming.ldap.LdapContext;
045    
046    /**
047     * @author Michael C. Han
048     * @author Brian Wing Shun Chan
049     * @author Marcellus Tavares
050     * @author Wesley Gong
051     * @author Vilmos Papp
052     */
053    @DoPrivileged
054    public class PortalLDAPExporterImpl implements PortalLDAPExporter {
055    
056            @Override
057            public void exportToLDAP(
058                            Contact contact, Map<String, Serializable> contactExpandoAttributes)
059                    throws Exception {
060    
061                    long companyId = contact.getCompanyId();
062    
063                    if (!PrefsPropsUtil.getBoolean(
064                                    companyId, PropsKeys.LDAP_AUTH_ENABLED,
065                                    PropsValues.LDAP_AUTH_ENABLED) ||
066                            !LDAPSettingsUtil.isExportEnabled(companyId)) {
067    
068                            return;
069                    }
070    
071                    User user = UserLocalServiceUtil.getUserByContactId(
072                            contact.getContactId());
073    
074                    if (user.isDefaultUser() ||
075                            (user.getStatus() != WorkflowConstants.STATUS_APPROVED)) {
076    
077                            return;
078                    }
079    
080                    long ldapServerId = PortalLDAPUtil.getLdapServerId(
081                            companyId, user.getScreenName(), user.getEmailAddress());
082    
083                    LdapContext ldapContext = PortalLDAPUtil.getContext(
084                            ldapServerId, companyId);
085    
086                    try {
087                            if (ldapContext == null) {
088                                    return;
089                            }
090    
091                            Properties contactMappings = LDAPSettingsUtil.getContactMappings(
092                                    ldapServerId, companyId);
093                            Properties contactExpandoMappings =
094                                    LDAPSettingsUtil.getContactExpandoMappings(
095                                            ldapServerId, companyId);
096    
097                            Binding binding = PortalLDAPUtil.getUser(
098                                    ldapServerId, contact.getCompanyId(), user.getScreenName(),
099                                    user.getEmailAddress());
100    
101                            if (binding == null) {
102                                    Properties userMappings = LDAPSettingsUtil.getUserMappings(
103                                            ldapServerId, companyId);
104    
105                                    binding = addUser(
106                                            ldapServerId, ldapContext, user, userMappings);
107                            }
108    
109                            Name name = new CompositeName();
110    
111                            name.add(
112                                    PortalLDAPUtil.getNameInNamespace(
113                                            ldapServerId, companyId, binding));
114    
115                            Modifications modifications =
116                                    _portalToLDAPConverter.getLDAPContactModifications(
117                                            contact, contactExpandoAttributes, contactMappings,
118                                            contactExpandoMappings);
119    
120                            if (modifications == null) {
121                                    return;
122                            }
123    
124                            ModificationItem[] modificationItems = modifications.getItems();
125    
126                            ldapContext.modifyAttributes(name, modificationItems);
127                    }
128                    finally {
129                            if (ldapContext != null) {
130                                    ldapContext.close();
131                            }
132                    }
133            }
134    
135            @Override
136            public void exportToLDAP(
137                            long userId, long userGroupId, LDAPOperation ldapOperation)
138                    throws Exception {
139    
140                    User user = UserLocalServiceUtil.getUser(userId);
141    
142                    long companyId = user.getCompanyId();
143    
144                    if (!PrefsPropsUtil.getBoolean(
145                                    companyId, PropsKeys.LDAP_AUTH_ENABLED,
146                                    PropsValues.LDAP_AUTH_ENABLED) ||
147                            !LDAPSettingsUtil.isExportEnabled(companyId) ||
148                            !LDAPSettingsUtil.isExportGroupEnabled(companyId)) {
149    
150                            return;
151                    }
152    
153                    long ldapServerId = PortalLDAPUtil.getLdapServerId(
154                            companyId, user.getScreenName(), user.getEmailAddress());
155    
156                    LdapContext ldapContext = PortalLDAPUtil.getContext(
157                            ldapServerId, companyId);
158    
159                    if (ldapContext == null) {
160                            return;
161                    }
162    
163                    UserGroup userGroup = UserGroupLocalServiceUtil.getUserGroup(
164                            userGroupId);
165    
166                    Properties groupMappings = LDAPSettingsUtil.getGroupMappings(
167                            ldapServerId, companyId);
168                    Properties userMappings = LDAPSettingsUtil.getUserMappings(
169                            ldapServerId, companyId);
170    
171                    Binding binding = PortalLDAPUtil.getGroup(
172                            ldapServerId, companyId, userGroup.getName());
173    
174                    try {
175                            if (binding == null) {
176                                    if (ldapOperation == LDAPOperation.ADD) {
177                                            addGroup(
178                                                    ldapServerId, ldapContext, userGroup, user,
179                                                    groupMappings, userMappings);
180                                    }
181    
182                                    return;
183                            }
184    
185                            Name name = new CompositeName();
186    
187                            name.add(
188                                    PortalLDAPUtil.getNameInNamespace(
189                                            ldapServerId, companyId, binding));
190    
191                            Modifications modifications =
192                                    _portalToLDAPConverter.getLDAPGroupModifications(
193                                            ldapServerId, userGroup, user, groupMappings, userMappings,
194                                            ldapOperation);
195    
196                            ModificationItem[] modificationItems = modifications.getItems();
197    
198                            ldapContext.modifyAttributes(name, modificationItems);
199                    }
200                    catch (SchemaViolationException sve) {
201                            String fullGroupDN = PortalLDAPUtil.getNameInNamespace(
202                                    ldapServerId, companyId, binding);
203    
204                            Attributes attributes = PortalLDAPUtil.getGroupAttributes(
205                                    ldapServerId, companyId, ldapContext, fullGroupDN, true);
206    
207                            Attribute groupMembers = attributes.get(
208                                    groupMappings.getProperty(GroupConverterKeys.USER));
209    
210                            if ((groupMembers != null) && (groupMembers.size() == 1)) {
211                                    ldapContext.unbind(fullGroupDN);
212                            }
213                    }
214                    finally {
215                            if (ldapContext != null) {
216                                    ldapContext.close();
217                            }
218                    }
219            }
220    
221            @Override
222            public void exportToLDAP(
223                            User user, Map<String, Serializable> userExpandoAttributes)
224                    throws Exception {
225    
226                    if (user.isDefaultUser() ||
227                            (user.getStatus() != WorkflowConstants.STATUS_APPROVED)) {
228    
229                            return;
230                    }
231    
232                    long companyId = user.getCompanyId();
233    
234                    if (!PrefsPropsUtil.getBoolean(
235                                    companyId, PropsKeys.LDAP_AUTH_ENABLED,
236                                    PropsValues.LDAP_AUTH_ENABLED) ||
237                            !LDAPSettingsUtil.isExportEnabled(companyId)) {
238    
239                            return;
240                    }
241    
242                    long ldapServerId = PortalLDAPUtil.getLdapServerId(
243                            companyId, user.getScreenName(), user.getEmailAddress());
244    
245                    LdapContext ldapContext = PortalLDAPUtil.getContext(
246                            ldapServerId, companyId);
247    
248                    try {
249                            if (ldapContext == null) {
250                                    return;
251                            }
252    
253                            Properties userMappings = LDAPSettingsUtil.getUserMappings(
254                                    ldapServerId, companyId);
255                            Properties userExpandoMappings =
256                                    LDAPSettingsUtil.getUserExpandoMappings(
257                                            ldapServerId, companyId);
258    
259                            Binding binding = PortalLDAPUtil.getUser(
260                                    ldapServerId, user.getCompanyId(), user.getScreenName(),
261                                    user.getEmailAddress(), true);
262    
263                            if (binding == null) {
264                                    binding = addUser(
265                                            ldapServerId, ldapContext, user, userMappings);
266                            }
267    
268                            Name name = new CompositeName();
269    
270                            name.add(
271                                    PortalLDAPUtil.getNameInNamespace(
272                                            ldapServerId, companyId, binding));
273    
274                            Modifications modifications =
275                                    _portalToLDAPConverter.getLDAPUserModifications(
276                                            user, userExpandoAttributes, userMappings,
277                                            userExpandoMappings);
278    
279                            if (modifications == null) {
280                                    return;
281                            }
282    
283                            ModificationItem[] modificationItems = modifications.getItems();
284    
285                            ldapContext.modifyAttributes(name, modificationItems);
286    
287                            if (!LDAPSettingsUtil.isExportGroupEnabled(companyId)) {
288                                    return;
289                            }
290    
291                            List<UserGroup> userGroups =
292                                    UserGroupLocalServiceUtil.getUserUserGroups(user.getUserId());
293    
294                            for (UserGroup userGroup : userGroups) {
295                                    exportToLDAP(
296                                            user.getUserId(), userGroup.getUserGroupId(),
297                                            LDAPOperation.ADD);
298                            }
299    
300                            Modifications groupModifications =
301                                    _portalToLDAPConverter.getLDAPUserGroupModifications(
302                                            ldapServerId, userGroups, user, userMappings);
303    
304                            ModificationItem[] groupModificationItems =
305                                    groupModifications.getItems();
306    
307                            if (groupModificationItems.length > 0) {
308                                    ldapContext.modifyAttributes(name, groupModificationItems);
309                            }
310                    }
311                    catch (NameNotFoundException nnfe) {
312                            if (PrefsPropsUtil.getBoolean(
313                                            companyId, PropsKeys.LDAP_AUTH_REQUIRED)) {
314    
315                                    throw nnfe;
316                            }
317    
318                            _log.error(nnfe, nnfe);
319                    }
320                    finally {
321                            if (ldapContext != null) {
322                                    ldapContext.close();
323                            }
324                    }
325            }
326    
327            public void setPortalToLDAPConverter(
328                    PortalToLDAPConverter portalToLDAPConverter) {
329    
330                    _portalToLDAPConverter = portalToLDAPConverter;
331            }
332    
333            protected Binding addGroup(
334                            long ldapServerId, LdapContext ldapContext, UserGroup userGroup,
335                            User user, Properties groupMappings, Properties userMappings)
336                    throws Exception {
337    
338                    Name name = new CompositeName();
339    
340                    name.add(
341                            _portalToLDAPConverter.getGroupDNName(
342                                    ldapServerId, userGroup, groupMappings));
343    
344                    Attributes attributes = _portalToLDAPConverter.getLDAPGroupAttributes(
345                            ldapServerId, userGroup, user, groupMappings, userMappings);
346    
347                    ldapContext.bind(name, new PortalLDAPContext(attributes));
348    
349                    Binding binding = PortalLDAPUtil.getGroup(
350                            ldapServerId, userGroup.getCompanyId(), userGroup.getName());
351    
352                    return binding;
353            }
354    
355            protected Binding addUser(
356                            long ldapServerId, LdapContext ldapContext, User user,
357                            Properties userMappings)
358                    throws Exception {
359    
360                    Name name = new CompositeName();
361    
362                    name.add(
363                            _portalToLDAPConverter.getUserDNName(
364                                    ldapServerId, user, userMappings));
365    
366                    Attributes attributes = _portalToLDAPConverter.getLDAPUserAttributes(
367                            ldapServerId, user, userMappings);
368    
369                    ldapContext.bind(name, new PortalLDAPContext(attributes));
370    
371                    Binding binding = PortalLDAPUtil.getUser(
372                            ldapServerId, user.getCompanyId(), user.getScreenName(),
373                            user.getEmailAddress());
374    
375                    return binding;
376            }
377    
378            private static final Log _log = LogFactoryUtil.getLog(
379                    PortalLDAPExporterImpl.class);
380    
381            private PortalToLDAPConverter _portalToLDAPConverter;
382    
383    }