1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.security.ldap;
24  
25  import com.liferay.portal.NoSuchUserException;
26  import com.liferay.portal.NoSuchUserGroupException;
27  import com.liferay.portal.PortalException;
28  import com.liferay.portal.SystemException;
29  import com.liferay.portal.kernel.log.Log;
30  import com.liferay.portal.kernel.log.LogFactoryUtil;
31  import com.liferay.portal.kernel.log.LogUtil;
32  import com.liferay.portal.kernel.util.CalendarFactoryUtil;
33  import com.liferay.portal.kernel.util.PropertiesUtil;
34  import com.liferay.portal.kernel.util.StringMaker;
35  import com.liferay.portal.kernel.util.StringPool;
36  import com.liferay.portal.kernel.util.StringUtil;
37  import com.liferay.portal.kernel.util.Validator;
38  import com.liferay.portal.model.Company;
39  import com.liferay.portal.model.CompanyConstants;
40  import com.liferay.portal.model.Contact;
41  import com.liferay.portal.model.User;
42  import com.liferay.portal.model.UserGroup;
43  import com.liferay.portal.service.CompanyLocalServiceUtil;
44  import com.liferay.portal.service.UserGroupLocalServiceUtil;
45  import com.liferay.portal.service.UserLocalServiceUtil;
46  import com.liferay.portal.util.PrefsPropsUtil;
47  import com.liferay.portal.util.PropsUtil;
48  import com.liferay.portal.util.PropsValues;
49  import com.liferay.util.ldap.LDAPUtil;
50  import com.liferay.util.ldap.Modifications;
51  
52  import java.text.DateFormat;
53  import java.text.ParseException;
54  import java.text.SimpleDateFormat;
55  
56  import java.util.Calendar;
57  import java.util.Date;
58  import java.util.List;
59  import java.util.Locale;
60  import java.util.Properties;
61  
62  import javax.naming.Binding;
63  import javax.naming.Context;
64  import javax.naming.NameNotFoundException;
65  import javax.naming.NamingEnumeration;
66  import javax.naming.directory.Attribute;
67  import javax.naming.directory.Attributes;
68  import javax.naming.directory.ModificationItem;
69  import javax.naming.directory.SearchControls;
70  import javax.naming.directory.SearchResult;
71  import javax.naming.ldap.InitialLdapContext;
72  import javax.naming.ldap.LdapContext;
73  
74  /**
75   * <a href="PortalLDAPUtil.java.html"><b><i>View Source</i></b></a>
76   *
77   * @author Michael Young
78   * @author Brian Wing Shun Chan
79   * @author Jerry Niu
80   * @author Scott Lee
81   * @author Herv� M�nage
82   *
83   */
84  public class PortalLDAPUtil {
85  
86      public static final String IMPORT_BY_USER = "user";
87  
88      public static final String IMPORT_BY_GROUP = "group";
89  
90      public static void exportToLDAP(Contact contact) throws Exception {
91          long companyId = contact.getCompanyId();
92  
93          if (!isAuthEnabled(companyId) || !isExportEnabled(companyId)) {
94              return;
95          }
96  
97          LdapContext ctx = getContext(companyId);
98  
99          if (ctx == null) {
100             return;
101         }
102 
103         User user = UserLocalServiceUtil.getUserByContactId(
104             contact.getContactId());
105 
106         Properties userMappings = getUserMappings(companyId);
107         Binding binding = getUser(contact.getCompanyId(), user.getScreenName());
108         String name = StringPool.BLANK;
109 
110         if (binding == null) {
111 
112             // Generate full DN based on user DN
113 
114             StringMaker sm = new StringMaker();
115 
116             sm.append(userMappings.getProperty("screenName"));
117             sm.append(StringPool.EQUAL);
118             sm.append(user.getScreenName());
119             sm.append(StringPool.COMMA);
120             sm.append(getUsersDN(companyId));
121 
122             name = sm.toString();
123 
124             // Create new user in LDAP
125 
126             LDAPUser ldapUser = (LDAPUser)Class.forName(
127                 PropsValues.LDAP_USER_IMPL).newInstance();
128 
129             ldapUser.setUser(user);
130 
131             ctx.bind(name, ldapUser);
132         }
133         else {
134 
135             // Modify existing LDAP user record
136 
137             name = getNameInNamespace(companyId, binding);
138 
139             Modifications mods = Modifications.getInstance();
140 
141             mods.addItem(
142                 userMappings.getProperty("firstName"), contact.getFirstName());
143             mods.addItem(
144                 userMappings.getProperty("lastName"), contact.getLastName());
145 
146             ModificationItem[] modItems = mods.getItems();
147 
148             ctx.modifyAttributes(name, modItems);
149         }
150 
151         ctx.close();
152     }
153 
154     public static void exportToLDAP(User user) throws Exception {
155         long companyId = user.getCompanyId();
156 
157         if (!isAuthEnabled(companyId) || !isExportEnabled(companyId)) {
158             return;
159         }
160 
161         LdapContext ctx = getContext(companyId);
162 
163         if (ctx == null) {
164             return;
165         }
166 
167         Properties userMappings = getUserMappings(companyId);
168         Binding binding = getUser(user.getCompanyId(), user.getScreenName());
169         String name = StringPool.BLANK;
170 
171         if (binding == null) {
172 
173             // Generate full DN based on user DN
174 
175             StringMaker sm = new StringMaker();
176 
177             sm.append(userMappings.getProperty("screenName"));
178             sm.append(StringPool.EQUAL);
179             sm.append(user.getScreenName());
180             sm.append(StringPool.COMMA);
181             sm.append(getUsersDN(companyId));
182 
183             name = sm.toString();
184 
185             // Create new user in LDAP
186 
187             LDAPUser ldapUser = (LDAPUser)Class.forName(
188                 PropsValues.LDAP_USER_IMPL).newInstance();
189 
190             ldapUser.setUser(user);
191 
192             ctx.bind(name, ldapUser);
193         }
194         else {
195 
196             // Modify existing LDAP user record
197 
198             name = getNameInNamespace(companyId, binding);
199 
200             Modifications mods = Modifications.getInstance();
201 
202             if (user.isPasswordModified() &&
203                 Validator.isNotNull(user.getPasswordUnencrypted())) {
204 
205                 mods.addItem(
206                     userMappings.getProperty("password"),
207                     user.getPasswordUnencrypted());
208             }
209 
210             mods.addItem(
211                 userMappings.getProperty("emailAddress"),
212                 user.getEmailAddress());
213 
214             ModificationItem[] modItems = mods.getItems();
215 
216             ctx.modifyAttributes(name, modItems);
217         }
218 
219         ctx.close();
220     }
221 
222     public static Attributes getAttributes(
223             LdapContext ctx, String fullDistinguishedName)
224         throws Exception {
225 
226         String[] attrIds = {
227             "creatorsName", "createTimestamp", "modifiersName",
228             "modifyTimestamp"
229         };
230 
231         Attributes attrs = ctx.getAttributes(fullDistinguishedName);
232 
233         NamingEnumeration<? extends Attribute> enu = ctx.getAttributes(
234             fullDistinguishedName, attrIds).getAll();
235 
236         while (enu.hasMore()) {
237             attrs.put(enu.next());
238         }
239 
240         return attrs;
241     }
242 
243     public static String getAuthSearchFilter(
244             long companyId, String emailAddress, String screenName,
245             String userId)
246         throws PortalException, SystemException {
247 
248         String filter = PrefsPropsUtil.getString(
249             companyId, PropsUtil.LDAP_AUTH_SEARCH_FILTER);
250 
251         if (_log.isDebugEnabled()) {
252             _log.debug("Search filter before transformation " + filter);
253         }
254 
255         filter = StringUtil.replace(
256             filter,
257             new String[] {
258                 "@company_id@", "@email_address@", "@screen_name@", "@user_id@"
259             },
260             new String[] {
261                 String.valueOf(companyId), emailAddress, screenName,
262                 userId
263             });
264 
265         if (_log.isDebugEnabled()) {
266             _log.debug("Search filter after transformation " + filter);
267         }
268 
269         return filter;
270     }
271 
272     public static LdapContext getContext(long companyId) throws Exception {
273         String baseProviderURL = PrefsPropsUtil.getString(
274             companyId, PropsUtil.LDAP_BASE_PROVIDER_URL);
275         String pricipal = PrefsPropsUtil.getString(
276             companyId, PropsUtil.LDAP_SECURITY_PRINCIPAL);
277         String credentials = PrefsPropsUtil.getString(
278             companyId, PropsUtil.LDAP_SECURITY_CREDENTIALS);
279 
280         return getContext(companyId, baseProviderURL, pricipal, credentials);
281     }
282 
283     public static LdapContext getContext(
284             long companyId, String providerURL, String pricipal,
285             String credentials)
286         throws Exception {
287 
288         Properties env = new Properties();
289 
290         env.put(
291             Context.INITIAL_CONTEXT_FACTORY,
292             PrefsPropsUtil.getString(
293                 companyId, PropsUtil.LDAP_FACTORY_INITIAL));
294         env.put(Context.PROVIDER_URL, providerURL);
295         env.put(Context.SECURITY_PRINCIPAL, pricipal);
296         env.put(Context.SECURITY_CREDENTIALS, credentials);
297 
298         LogUtil.debug(_log, env);
299 
300         LdapContext ctx = null;
301 
302         try {
303             ctx = new InitialLdapContext(env, null);
304         }
305         catch (Exception e) {
306             if (_log.isWarnEnabled()) {
307                 _log.warn("Failed to bind to the LDAP server");
308             }
309 
310             if (_log.isDebugEnabled()) {
311                 _log.debug(e);
312             }
313         }
314 
315         return ctx;
316     }
317 
318     public static Properties getGroupMappings(long companyId)
319         throws Exception {
320 
321         Properties groupMappings = PropertiesUtil.load(
322             PrefsPropsUtil.getString(companyId, PropsUtil.LDAP_GROUP_MAPPINGS));
323 
324         LogUtil.debug(_log, groupMappings);
325 
326         return groupMappings;
327     }
328 
329     public static NamingEnumeration<SearchResult> getGroups(
330             long companyId, LdapContext ctx, int maxResults)
331         throws Exception {
332 
333         String baseDN = PrefsPropsUtil.getString(
334             companyId, PropsUtil.LDAP_BASE_DN);
335         String groupFilter = PrefsPropsUtil.getString(
336             companyId, PropsUtil.LDAP_IMPORT_GROUP_SEARCH_FILTER);
337 
338         return getGroups(companyId, ctx, maxResults, baseDN, groupFilter);
339     }
340 
341     public static NamingEnumeration<SearchResult> getGroups(
342             long companyId, LdapContext ctx, int maxResults, String baseDN,
343             String groupFilter)
344         throws Exception {
345 
346         SearchControls cons = new SearchControls(
347             SearchControls.SUBTREE_SCOPE, maxResults, 0, null, false, false);
348 
349         return ctx.search(baseDN, groupFilter, cons);
350     }
351 
352     public static String getNameInNamespace(long companyId, Binding binding)
353         throws Exception {
354 
355         String baseDN = PrefsPropsUtil.getString(
356             companyId, PropsUtil.LDAP_BASE_DN);
357 
358         if (Validator.isNull(baseDN)) {
359             return binding.getName();
360         }
361         else {
362             StringMaker sm = new StringMaker();
363 
364             sm.append(binding.getName());
365             sm.append(StringPool.COMMA);
366             sm.append(baseDN);
367 
368             return sm.toString();
369         }
370     }
371 
372     public static Binding getUser(long companyId, String screenName)
373         throws Exception {
374 
375         LdapContext ctx = getContext(companyId);
376 
377         if (ctx == null) {
378             return null;
379         }
380 
381         String baseDN = PrefsPropsUtil.getString(
382             companyId, PropsUtil.LDAP_BASE_DN);
383 
384         Properties userMappings = getUserMappings(companyId);
385 
386         StringMaker filter = new StringMaker();
387 
388         filter.append(StringPool.OPEN_PARENTHESIS);
389         filter.append(userMappings.getProperty("screenName"));
390         filter.append(StringPool.EQUAL);
391         filter.append(screenName);
392         filter.append(StringPool.CLOSE_PARENTHESIS);
393 
394         SearchControls cons = new SearchControls(
395             SearchControls.SUBTREE_SCOPE, 1, 0, null, false, false);
396 
397         NamingEnumeration<SearchResult> enu = ctx.search(
398             baseDN, filter.toString(), cons);
399 
400         ctx.close();
401 
402         if (enu.hasMore()) {
403             Binding binding = enu.next();
404 
405             return binding;
406         }
407         else {
408             return null;
409         }
410     }
411 
412     public static Properties getUserMappings(long companyId) throws Exception {
413         Properties userMappings = PropertiesUtil.load(
414             PrefsPropsUtil.getString(companyId, PropsUtil.LDAP_USER_MAPPINGS));
415 
416         LogUtil.debug(_log, userMappings);
417 
418         return userMappings;
419     }
420 
421     public static NamingEnumeration<SearchResult> getUsers(
422             long companyId, LdapContext ctx, int maxResults)
423         throws Exception {
424 
425         String baseDN = PrefsPropsUtil.getString(
426             companyId, PropsUtil.LDAP_BASE_DN);
427         String userFilter = PrefsPropsUtil.getString(
428             companyId, PropsUtil.LDAP_IMPORT_USER_SEARCH_FILTER);
429 
430         return getUsers(companyId, ctx, maxResults, baseDN, userFilter);
431     }
432 
433     public static NamingEnumeration<SearchResult> getUsers(
434             long companyId, LdapContext ctx, int maxResults, String baseDN,
435             String userFilter)
436         throws Exception {
437 
438         SearchControls cons = new SearchControls(
439             SearchControls.SUBTREE_SCOPE, maxResults, 0, null, false, false);
440 
441         return ctx.search(baseDN, userFilter, cons);
442     }
443 
444     public static String getUsersDN(long companyId) throws Exception {
445         return PrefsPropsUtil.getString(companyId, PropsUtil.LDAP_USERS_DN);
446     }
447 
448     public static boolean hasUser(long companyId, String screenName)
449         throws Exception {
450 
451         if (getUser(companyId, screenName) != null) {
452             return true;
453         }
454         else {
455             return false;
456         }
457     }
458 
459     public static void importFromLDAP() throws Exception {
460         List<Company> companies = CompanyLocalServiceUtil.getCompanies();
461 
462         for (Company company : companies) {
463             importFromLDAP(company.getCompanyId());
464         }
465     }
466 
467     public static void importFromLDAP(long companyId) throws Exception {
468         if (!isImportEnabled(companyId)) {
469             return;
470         }
471 
472         LdapContext ctx = getContext(companyId);
473 
474         if (ctx == null) {
475             return;
476         }
477 
478         try {
479             String importMethod = PrefsPropsUtil.getString(
480                 companyId, PropsUtil.LDAP_IMPORT_METHOD);
481 
482             if (importMethod.equals(IMPORT_BY_USER)) {
483                 NamingEnumeration<SearchResult> enu = getUsers(
484                     companyId, ctx, 0);
485 
486                 // Loop through all LDAP users
487 
488                 while (enu.hasMore()) {
489                     SearchResult result = enu.next();
490 
491                     Attributes attrs = getAttributes(
492                         ctx, getNameInNamespace(companyId, result));
493 
494                     importLDAPUser(
495                         companyId, ctx, attrs, StringPool.BLANK, true);
496                 }
497             }
498             else if (importMethod.equals(IMPORT_BY_GROUP)) {
499                 NamingEnumeration<SearchResult> enu = getGroups(
500                     companyId, ctx, 0);
501 
502                 // Loop through all LDAP groups
503 
504                 while (enu.hasMore()) {
505                     SearchResult result = enu.next();
506 
507                     Attributes attrs = getAttributes(
508                         ctx, getNameInNamespace(companyId, result));
509 
510                     importLDAPGroup(companyId, ctx, attrs, true);
511                 }
512             }
513         }
514         catch (Exception e) {
515             _log.error("Error importing LDAP users and groups", e);
516         }
517         finally {
518             if (ctx != null) {
519                 ctx.close();
520             }
521         }
522     }
523 
524     public static UserGroup importLDAPGroup(
525             long companyId, LdapContext ctx, Attributes attrs,
526             boolean importGroupMembership)
527         throws Exception {
528 
529         AttributesTransformer attrsTransformer =
530             AttributesTransformerFactory.getInstance();
531 
532         attrs = attrsTransformer.transformGroup(attrs);
533 
534         Properties groupMappings = getGroupMappings(companyId);
535 
536         LogUtil.debug(_log, groupMappings);
537 
538         String groupName = LDAPUtil.getAttributeValue(
539             attrs, groupMappings.getProperty("groupName")).toLowerCase();
540         String description = LDAPUtil.getAttributeValue(
541             attrs, groupMappings.getProperty("description"));
542 
543         // Get or create user group
544 
545         UserGroup userGroup = null;
546 
547         try {
548             userGroup = UserGroupLocalServiceUtil.getUserGroup(
549                 companyId, groupName);
550 
551             UserGroupLocalServiceUtil.updateUserGroup(
552                 companyId, userGroup.getUserGroupId(), groupName, description);
553         }
554         catch (NoSuchUserGroupException nsuge) {
555             if (_log.isDebugEnabled()) {
556                 _log.debug("Adding user group to portal " + groupName);
557             }
558 
559             long defaultUserId = UserLocalServiceUtil.getDefaultUserId(
560                 companyId);
561 
562             try {
563                 userGroup = UserGroupLocalServiceUtil.addUserGroup(
564                     defaultUserId, companyId, groupName, description);
565             }
566             catch (Exception e) {
567                 if (_log.isWarnEnabled()) {
568                     _log.warn("Could not create user group " + groupName);
569                 }
570 
571                 if (_log.isDebugEnabled()) {
572                     _log.debug(e, e);
573                 }
574             }
575         }
576 
577         // Import users and membership
578 
579         if (importGroupMembership && (userGroup != null)) {
580             Attribute attr = attrs.get(groupMappings.getProperty("user"));
581 
582             if (attr != null){
583                 _importUsersAndMembershipFromLDAPGroup(
584                     companyId, ctx, userGroup.getUserGroupId(), attr);
585             }
586         }
587 
588         return userGroup;
589     }
590 
591     public static User importLDAPUser(
592             long companyId, LdapContext ctx, Attributes attrs, String password,
593             boolean importGroupMembership)
594         throws Exception {
595 
596         AttributesTransformer attrsTransformer =
597             AttributesTransformerFactory.getInstance();
598 
599         attrs = attrsTransformer.transformUser(attrs);
600 
601         Properties userMappings = getUserMappings(companyId);
602 
603         LogUtil.debug(_log, userMappings);
604 
605         User defaultUser = UserLocalServiceUtil.getDefaultUser(companyId);
606 
607         boolean autoPassword = false;
608         boolean updatePassword = true;
609 
610         if (password.equals(StringPool.BLANK)) {
611             autoPassword = true;
612             updatePassword = false;
613         }
614 
615         long creatorUserId = 0;
616         boolean passwordReset = false;
617         boolean autoScreenName = false;
618         String screenName = LDAPUtil.getAttributeValue(
619             attrs, userMappings.getProperty("screenName")).toLowerCase();
620         String emailAddress = LDAPUtil.getAttributeValue(
621             attrs, userMappings.getProperty("emailAddress"));
622         Locale locale = defaultUser.getLocale();
623         String firstName = LDAPUtil.getAttributeValue(
624             attrs, userMappings.getProperty("firstName"));
625         String middleName = LDAPUtil.getAttributeValue(
626             attrs, userMappings.getProperty("middleName"));
627         String lastName = LDAPUtil.getAttributeValue(
628             attrs, userMappings.getProperty("lastName"));
629 
630         if (Validator.isNull(firstName) || Validator.isNull(lastName)) {
631             String fullName = LDAPUtil.getAttributeValue(
632                 attrs, userMappings.getProperty("fullName"));
633 
634             String[] names = LDAPUtil.splitFullName(fullName);
635 
636             firstName = names[0];
637             middleName = names[1];
638             lastName = names[2];
639         }
640 
641         int prefixId = 0;
642         int suffixId = 0;
643         boolean male = true;
644         int birthdayMonth = Calendar.JANUARY;
645         int birthdayDay = 1;
646         int birthdayYear = 1970;
647         String jobTitle = LDAPUtil.getAttributeValue(
648             attrs, userMappings.getProperty("jobTitle"));
649         long[] organizationIds = new long[0];
650         boolean sendEmail = false;
651 
652         if (_log.isDebugEnabled()) {
653             _log.debug(
654                 "Screen name " + screenName + " and email address " +
655                     emailAddress);
656         }
657 
658         if (Validator.isNull(screenName) || Validator.isNull(emailAddress)) {
659             if (_log.isWarnEnabled()) {
660                 _log.warn(
661                     "Cannot add user because screen name and email address " +
662                         "are required");
663             }
664 
665             return null;
666         }
667 
668         User user = null;
669 
670         try {
671 
672             // Find corresponding portal user
673 
674             String authType = PrefsPropsUtil.getString(
675                 companyId, PropsUtil.COMPANY_SECURITY_AUTH_TYPE,
676                 PropsValues.COMPANY_SECURITY_AUTH_TYPE);
677 
678             if (authType.equals(CompanyConstants.AUTH_TYPE_SN)) {
679                 user = UserLocalServiceUtil.getUserByScreenName(
680                     companyId, screenName);
681             }
682             else {
683                 user = UserLocalServiceUtil.getUserByEmailAddress(
684                     companyId, emailAddress);
685             }
686 
687             // Skip if is default user
688 
689             if (user.isDefaultUser()) {
690                 return user;
691             }
692 
693             // Skip import if user fields has been already synced and if
694             // import is part of a scheduled import
695 
696             Date ldapUserModifiedDate = null;
697 
698             String modifiedDate = LDAPUtil.getAttributeValue(
699                 attrs, "modifyTimestamp");
700 
701             try {
702                 DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
703 
704                 ldapUserModifiedDate = dateFormat.parse(modifiedDate);
705 
706                 if (ldapUserModifiedDate.equals(user.getModifiedDate()) &&
707                     autoPassword) {
708 
709                     if (_log.isDebugEnabled()) {
710                         _log.debug(
711                             "User is already syncronized, skipping user " +
712                                 user.getEmailAddress());
713                     }
714 
715                     return user;
716                 }
717             }
718             catch (ParseException pe) {
719                 if (_log.isDebugEnabled()) {
720                     _log.debug(
721                         "Unable to parse LDAP modify timestamp " +
722                             modifiedDate);
723                 }
724 
725                 _log.debug(pe, pe);
726             }
727 
728             Contact contact = user.getContact();
729 
730             Calendar birthdayCal = CalendarFactoryUtil.getCalendar();
731 
732             birthdayCal.setTime(contact.getBirthday());
733 
734             birthdayMonth = birthdayCal.get(Calendar.MONTH);
735             birthdayDay = birthdayCal.get(Calendar.DATE);
736             birthdayYear = birthdayCal.get(Calendar.YEAR);
737 
738             // User exists so update user information
739 
740             if (updatePassword) {
741                 user = UserLocalServiceUtil.updatePassword(
742                     user.getUserId(), password, password, passwordReset,
743                     true);
744             }
745 
746             user = UserLocalServiceUtil.updateUser(
747                 user.getUserId(), password, user.isPasswordReset(), screenName,
748                 emailAddress, user.getLanguageId(), user.getTimeZoneId(),
749                 user.getGreeting(), user.getComments(), firstName, middleName,
750                 lastName, contact.getPrefixId(), contact.getSuffixId(),
751                 contact.getMale(), birthdayMonth, birthdayDay, birthdayYear,
752                 contact.getSmsSn(), contact.getAimSn(), contact.getIcqSn(),
753                 contact.getJabberSn(), contact.getMsnSn(), contact.getSkypeSn(),
754                 contact.getYmSn(), jobTitle, user.getOrganizationIds());
755 
756             if (ldapUserModifiedDate != null) {
757                 UserLocalServiceUtil.updateModifiedDate(
758                     user.getUserId(), ldapUserModifiedDate);
759             }
760         }
761         catch (NoSuchUserException nsue) {
762 
763             // User does not exist so create
764 
765         }
766 
767         if (user == null) {
768             try {
769                 if (_log.isDebugEnabled()) {
770                     _log.debug("Adding user to portal " + emailAddress);
771                 }
772 
773                 user = UserLocalServiceUtil.addUser(
774                     creatorUserId, companyId, autoPassword, password, password,
775                     autoScreenName, screenName, emailAddress, locale, firstName,
776                     middleName, lastName, prefixId, suffixId, male,
777                     birthdayMonth, birthdayDay, birthdayYear, jobTitle,
778                     organizationIds, sendEmail);
779             }
780             catch (Exception e){
781                 _log.error(
782                     "Problem adding user with screen name " + screenName +
783                         " and email address " + emailAddress,
784                     e);
785             }
786         }
787 
788         // Import user groups and membership
789 
790         if (importGroupMembership && (user != null)) {
791             String userMappingsGroup = userMappings.getProperty("group");
792 
793             if (userMappingsGroup != null) {
794                 Attribute attr = attrs.get(userMappingsGroup);
795 
796                 if (attr != null){
797                     _importGroupsAndMembershipFromLDAPUser(
798                         companyId, ctx, user.getUserId(), attr);
799                 }
800             }
801         }
802 
803         return user;
804     }
805 
806     public static boolean isAuthEnabled(long companyId)
807         throws PortalException, SystemException {
808 
809         if (PrefsPropsUtil.getBoolean(
810                 companyId, PropsUtil.LDAP_AUTH_ENABLED,
811                 PropsValues.LDAP_AUTH_ENABLED)) {
812 
813             return true;
814         }
815         else {
816             return false;
817         }
818     }
819 
820     public static boolean isExportEnabled(long companyId)
821         throws PortalException, SystemException {
822 
823         if (PrefsPropsUtil.getBoolean(
824                 companyId, PropsUtil.LDAP_EXPORT_ENABLED,
825                 PropsValues.LDAP_EXPORT_ENABLED)) {
826 
827             return true;
828         }
829         else {
830             return false;
831         }
832     }
833 
834     public static boolean isImportEnabled(long companyId)
835         throws PortalException, SystemException {
836 
837         if (PrefsPropsUtil.getBoolean(
838                 companyId, PropsUtil.LDAP_IMPORT_ENABLED,
839                 PropsValues.LDAP_IMPORT_ENABLED)) {
840 
841             return true;
842         }
843         else {
844             return false;
845         }
846     }
847 
848     public static boolean isImportOnStartup(long companyId)
849         throws PortalException, SystemException {
850 
851         if (PrefsPropsUtil.getBoolean(
852                 companyId, PropsUtil.LDAP_IMPORT_ON_STARTUP)) {
853 
854             return true;
855         }
856         else {
857             return false;
858         }
859     }
860 
861     public static boolean isNtlmEnabled(long companyId)
862         throws PortalException, SystemException {
863 
864         if (!isAuthEnabled(companyId)) {
865             return false;
866         }
867 
868         if (PrefsPropsUtil.getBoolean(companyId, PropsUtil.NTLM_AUTH_ENABLED)) {
869             return true;
870         }
871         else {
872             return false;
873         }
874     }
875 
876     public static boolean isPasswordPolicyEnabled(long companyId)
877         throws PortalException, SystemException {
878 
879         if (PrefsPropsUtil.getBoolean(
880                 companyId, PropsUtil.LDAP_PASSWORD_POLICY_ENABLED,
881                 PropsValues.LDAP_PASSWORD_POLICY_ENABLED)) {
882 
883             return true;
884         }
885         else {
886             return false;
887         }
888     }
889 
890     private static void _importGroupsAndMembershipFromLDAPUser(
891             long companyId, LdapContext ctx, long userId, Attribute attr)
892         throws Exception {
893 
894         // Remove all user group membership from user
895 
896         UserGroupLocalServiceUtil.clearUserUserGroups(userId);
897 
898         for (int i = 0; i < attr.size(); i++) {
899 
900             // Find group in LDAP
901 
902             String fullGroupDN = (String)attr.get(i);
903 
904             Attributes groupAttrs = null;
905 
906             try {
907                 groupAttrs = getAttributes(ctx, fullGroupDN);
908             }
909             catch (NameNotFoundException nnfe) {
910                 _log.error(
911                     "LDAP group not found with fullGroupDN " + fullGroupDN);
912 
913                 _log.error(nnfe, nnfe);
914 
915                 continue;
916             }
917 
918             UserGroup userGroup = importLDAPGroup(
919                 companyId, ctx, groupAttrs, false);
920 
921             // Add user to user group
922 
923             if (userGroup != null) {
924                 if (_log.isDebugEnabled()) {
925                     _log.debug(
926                         "Adding " + userId + " to group " +
927                             userGroup.getUserGroupId());
928                 }
929 
930                 UserLocalServiceUtil.addUserGroupUsers(
931                     userGroup.getUserGroupId(), new long[] {userId});
932             }
933         }
934     }
935 
936     private static void _importUsersAndMembershipFromLDAPGroup(
937             long companyId, LdapContext ctx, long userGroupId, Attribute attr)
938         throws Exception {
939 
940         // Remove all user membership from user group
941 
942         UserLocalServiceUtil.clearUserGroupUsers(userGroupId);
943 
944         for (int i = 0; i < attr.size(); i++) {
945 
946             // Find user in LDAP
947 
948             String fullUserDN = (String)attr.get(i);
949 
950             Attributes userAttrs = null;
951 
952             try {
953                 userAttrs = getAttributes(ctx, fullUserDN);
954             }
955             catch (NameNotFoundException nnfe) {
956                 _log.error(
957                     "LDAP user not found with fullUserDN " + fullUserDN);
958 
959                 _log.error(nnfe, nnfe);
960 
961                 continue;
962             }
963 
964             User user = importLDAPUser(
965                 companyId, ctx, userAttrs, StringPool.BLANK, false);
966 
967             // Add user to user group
968 
969             if (user != null) {
970                 if (_log.isDebugEnabled()) {
971                     _log.debug(
972                         "Adding " + user.getUserId() + " to group " +
973                             userGroupId);
974                 }
975 
976                 UserLocalServiceUtil.addUserGroupUsers(
977                     userGroupId, new long[] {user.getUserId()});
978             }
979         }
980     }
981 
982     private static Log _log = LogFactoryUtil.getLog(PortalLDAPUtil.class);
983 
984 }