001    /**
002     * Copyright (c) 2000-2013 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.security.auth.AuthSettingsUtil;
026    import com.liferay.portal.service.UserGroupLocalServiceUtil;
027    import com.liferay.portal.service.UserLocalServiceUtil;
028    import com.liferay.portal.util.PrefsPropsUtil;
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     */
052    @DoPrivileged
053    public class PortalLDAPExporterImpl implements PortalLDAPExporter {
054    
055            @Override
056            public void exportToLDAP(
057                            Contact contact, Map<String, Serializable> contactExpandoAttributes)
058                    throws Exception {
059    
060                    long companyId = contact.getCompanyId();
061    
062                    if (!AuthSettingsUtil.isLDAPAuthEnabled(companyId) ||
063                            !LDAPSettingsUtil.isExportEnabled(companyId)) {
064    
065                            return;
066                    }
067    
068                    User user = UserLocalServiceUtil.getUserByContactId(
069                            contact.getContactId());
070    
071                    if (user.isDefaultUser() ||
072                            (user.getStatus() != WorkflowConstants.STATUS_APPROVED)) {
073    
074                            return;
075                    }
076    
077                    long ldapServerId = PortalLDAPUtil.getLdapServerId(
078                            companyId, user.getScreenName(), user.getEmailAddress());
079    
080                    LdapContext ldapContext = PortalLDAPUtil.getContext(
081                            ldapServerId, companyId);
082    
083                    try {
084                            if (ldapContext == null) {
085                                    return;
086                            }
087    
088                            Properties contactMappings = LDAPSettingsUtil.getContactMappings(
089                                    ldapServerId, companyId);
090                            Properties contactExpandoMappings =
091                                    LDAPSettingsUtil.getContactExpandoMappings(
092                                            ldapServerId, companyId);
093    
094                            Binding binding = PortalLDAPUtil.getUser(
095                                    ldapServerId, contact.getCompanyId(), user.getScreenName(),
096                                    user.getEmailAddress());
097    
098                            if (binding == null) {
099                                    Properties userMappings = LDAPSettingsUtil.getUserMappings(
100                                            ldapServerId, companyId);
101    
102                                    binding = addUser(
103                                            ldapServerId, ldapContext, user, userMappings);
104                            }
105    
106                            Name name = new CompositeName();
107    
108                            name.add(
109                                    PortalLDAPUtil.getNameInNamespace(
110                                            ldapServerId, companyId, binding));
111    
112                            Modifications modifications =
113                                    _portalToLDAPConverter.getLDAPContactModifications(
114                                            contact, contactExpandoAttributes, contactMappings,
115                                            contactExpandoMappings);
116    
117                            if (modifications == null) {
118                                    return;
119                            }
120    
121                            ModificationItem[] modificationItems = modifications.getItems();
122    
123                            ldapContext.modifyAttributes(name, modificationItems);
124                    }
125                    catch (Exception e) {
126                            throw e;
127                    }
128                    finally {
129                            if (ldapContext != null) {
130                                    ldapContext.close();
131                            }
132                    }
133            }
134    
135            /**
136             * @deprecated
137             */
138            @Override
139            public void exportToLDAP(long userId, long userGroupId) throws Exception {
140                    exportToLDAP(userId, userGroupId, LDAPOperation.ADD);
141            }
142    
143            @Override
144            public void exportToLDAP(
145                            long userId, long userGroupId, LDAPOperation ldapOperation)
146                    throws Exception {
147    
148                    User user = UserLocalServiceUtil.getUser(userId);
149    
150                    long companyId = user.getCompanyId();
151    
152                    if (!AuthSettingsUtil.isLDAPAuthEnabled(companyId) ||
153                            !LDAPSettingsUtil.isExportEnabled(companyId) ||
154                            !LDAPSettingsUtil.isExportGroupEnabled(companyId)) {
155    
156                            return;
157                    }
158    
159                    long ldapServerId = PortalLDAPUtil.getLdapServerId(
160                            companyId, user.getScreenName(), user.getEmailAddress());
161    
162                    LdapContext ldapContext = PortalLDAPUtil.getContext(
163                            ldapServerId, companyId);
164    
165                    if (ldapContext == null) {
166                            return;
167                    }
168    
169                    UserGroup userGroup = UserGroupLocalServiceUtil.getUserGroup(
170                            userGroupId);
171    
172                    Properties groupMappings = LDAPSettingsUtil.getGroupMappings(
173                            ldapServerId, companyId);
174                    Properties userMappings = LDAPSettingsUtil.getUserMappings(
175                            ldapServerId, companyId);
176    
177                    Binding binding = PortalLDAPUtil.getGroup(
178                            ldapServerId, companyId, userGroup.getName());
179    
180                    try {
181                            if (binding == null) {
182                                    if (ldapOperation == LDAPOperation.ADD) {
183                                            addGroup(
184                                                    ldapServerId, ldapContext, userGroup, user,
185                                                    groupMappings, userMappings);
186                                    }
187    
188                                    return;
189                            }
190    
191                            Name name = new CompositeName();
192    
193                            name.add(
194                                    PortalLDAPUtil.getNameInNamespace(
195                                            ldapServerId, companyId, binding));
196    
197                            Modifications modifications =
198                                    _portalToLDAPConverter.getLDAPGroupModifications(
199                                            ldapServerId, userGroup, user, groupMappings, userMappings,
200                                            ldapOperation);
201    
202                            ModificationItem[] modificationItems = modifications.getItems();
203    
204                            ldapContext.modifyAttributes(name, modificationItems);
205                    }
206                    catch (SchemaViolationException sve) {
207                            String fullGroupDN = PortalLDAPUtil.getNameInNamespace(
208                                    ldapServerId, companyId, binding);
209    
210                            Attributes attributes = PortalLDAPUtil.getGroupAttributes(
211                                    ldapServerId, companyId, ldapContext, fullGroupDN, true);
212    
213                            Attribute groupMembers = attributes.get(
214                                    groupMappings.getProperty(GroupConverterKeys.USER));
215    
216                            if ((groupMembers != null) && (groupMembers.size() == 1)) {
217                                    ldapContext.unbind(fullGroupDN);
218                            }
219                    }
220                    catch (Exception e) {
221                            throw e;
222                    }
223                    finally {
224                            if (ldapContext != null) {
225                                    ldapContext.close();
226                            }
227                    }
228            }
229    
230            @Override
231            public void exportToLDAP(
232                            User user, Map<String, Serializable> userExpandoAttributes)
233                    throws Exception {
234    
235                    if (user.isDefaultUser() ||
236                            (user.getStatus() != WorkflowConstants.STATUS_APPROVED)) {
237    
238                            return;
239                    }
240    
241                    long companyId = user.getCompanyId();
242    
243                    if (!AuthSettingsUtil.isLDAPAuthEnabled(companyId) ||
244                            !LDAPSettingsUtil.isExportEnabled(companyId)) {
245    
246                            return;
247                    }
248    
249                    long ldapServerId = PortalLDAPUtil.getLdapServerId(
250                            companyId, user.getScreenName(), user.getEmailAddress());
251    
252                    LdapContext ldapContext = PortalLDAPUtil.getContext(
253                            ldapServerId, companyId);
254    
255                    try {
256                            if (ldapContext == null) {
257                                    return;
258                            }
259    
260                            Properties userMappings = LDAPSettingsUtil.getUserMappings(
261                                    ldapServerId, companyId);
262                            Properties userExpandoMappings =
263                                    LDAPSettingsUtil.getUserExpandoMappings(
264                                            ldapServerId, companyId);
265    
266                            Binding binding = PortalLDAPUtil.getUser(
267                                    ldapServerId, user.getCompanyId(), user.getScreenName(),
268                                    user.getEmailAddress());
269    
270                            if (binding == null) {
271                                    binding = addUser(
272                                            ldapServerId, ldapContext, user, userMappings);
273                            }
274    
275                            Name name = new CompositeName();
276    
277                            name.add(
278                                    PortalLDAPUtil.getNameInNamespace(
279                                            ldapServerId, companyId, binding));
280    
281                            Modifications modifications =
282                                    _portalToLDAPConverter.getLDAPUserModifications(
283                                            user, userExpandoAttributes, userMappings,
284                                            userExpandoMappings);
285    
286                            if (modifications == null) {
287                                    return;
288                            }
289    
290                            ModificationItem[] modificationItems = modifications.getItems();
291    
292                            ldapContext.modifyAttributes(name, modificationItems);
293    
294                            if (!LDAPSettingsUtil.isExportGroupEnabled(companyId)) {
295                                    return;
296                            }
297    
298                            List<UserGroup> userGroups =
299                                    UserGroupLocalServiceUtil.getUserUserGroups(user.getUserId());
300    
301                            for (UserGroup userGroup : userGroups) {
302                                    exportToLDAP(
303                                            user.getUserId(), userGroup.getUserGroupId(),
304                                            LDAPOperation.ADD);
305                            }
306    
307                            Modifications groupModifications =
308                                    _portalToLDAPConverter.getLDAPUserGroupModifications(
309                                            ldapServerId, userGroups, user, userMappings);
310    
311                            ModificationItem[] groupModificationItems =
312                                    groupModifications.getItems();
313    
314                            if (groupModificationItems.length > 0) {
315                                    ldapContext.modifyAttributes(name, groupModificationItems);
316                            }
317                    }
318                    catch (NameNotFoundException nnfe) {
319                            if (PrefsPropsUtil.getBoolean(
320                                            companyId, PropsKeys.LDAP_AUTH_REQUIRED)) {
321    
322                                    throw nnfe;
323                            }
324    
325                            _log.error(nnfe, nnfe);
326                    }
327                    catch (Exception e) {
328                            throw e;
329                    }
330                    finally {
331                            if (ldapContext != null) {
332                                    ldapContext.close();
333                            }
334                    }
335            }
336    
337            public void setPortalToLDAPConverter(
338                    PortalToLDAPConverter portalToLDAPConverter) {
339    
340                    _portalToLDAPConverter = portalToLDAPConverter;
341            }
342    
343            protected Binding addGroup(
344                            long ldapServerId, LdapContext ldapContext, UserGroup userGroup,
345                            User user, Properties groupMappings, Properties userMappings)
346                    throws Exception {
347    
348                    Name name = new CompositeName();
349    
350                    name.add(
351                            _portalToLDAPConverter.getGroupDNName(
352                                    ldapServerId, userGroup, groupMappings));
353    
354                    Attributes attributes = _portalToLDAPConverter.getLDAPGroupAttributes(
355                            ldapServerId, userGroup, user, groupMappings, userMappings);
356    
357                    ldapContext.bind(name, new PortalLDAPContext(attributes));
358    
359                    Binding binding = PortalLDAPUtil.getGroup(
360                            ldapServerId, userGroup.getCompanyId(), userGroup.getName());
361    
362                    return binding;
363            }
364    
365            protected Binding addUser(
366                            long ldapServerId, LdapContext ldapContext, User user,
367                            Properties userMappings)
368                    throws Exception {
369    
370                    Name name = new CompositeName();
371    
372                    name.add(
373                            _portalToLDAPConverter.getUserDNName(
374                                    ldapServerId, user, userMappings));
375    
376                    Attributes attributes = _portalToLDAPConverter.getLDAPUserAttributes(
377                            ldapServerId, user, userMappings);
378    
379                    ldapContext.bind(name, new PortalLDAPContext(attributes));
380    
381                    Binding binding = PortalLDAPUtil.getUser(
382                            ldapServerId, user.getCompanyId(), user.getScreenName(),
383                            user.getEmailAddress());
384    
385                    return binding;
386            }
387    
388            private static Log _log = LogFactoryUtil.getLog(
389                    PortalLDAPExporterImpl.class);
390    
391            private PortalToLDAPConverter _portalToLDAPConverter;
392    
393    }