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.Contact;
40  import com.liferay.portal.model.User;
41  import com.liferay.portal.model.UserGroup;
42  import com.liferay.portal.model.impl.CompanyImpl;
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 enu = ctx.getAttributes(
234             fullDistinguishedName, attrIds).getAll();
235 
236         while (enu.hasMore()) {
237             attrs.put((Attribute)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 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 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 enu = ctx.search(baseDN, filter.toString(), cons);
398 
399         ctx.close();
400 
401         if (enu.hasMore()) {
402             Binding binding = (Binding)enu.next();
403 
404             return binding;
405         }
406         else {
407             return null;
408         }
409     }
410 
411     public static Properties getUserMappings(long companyId) throws Exception {
412         Properties userMappings = PropertiesUtil.load(
413             PrefsPropsUtil.getString(companyId, PropsUtil.LDAP_USER_MAPPINGS));
414 
415         LogUtil.debug(_log, userMappings);
416 
417         return userMappings;
418     }
419 
420     public static NamingEnumeration getUsers(
421             long companyId, LdapContext ctx, int maxResults)
422         throws Exception {
423 
424         String baseDN = PrefsPropsUtil.getString(
425             companyId, PropsUtil.LDAP_BASE_DN);
426         String userFilter = PrefsPropsUtil.getString(
427             companyId, PropsUtil.LDAP_IMPORT_USER_SEARCH_FILTER);
428 
429         return getUsers(companyId, ctx, maxResults, baseDN, userFilter);
430     }
431 
432     public static NamingEnumeration getUsers(
433             long companyId, LdapContext ctx, int maxResults, String baseDN,
434             String userFilter)
435         throws Exception {
436 
437         SearchControls cons = new SearchControls(
438             SearchControls.SUBTREE_SCOPE, maxResults, 0, null, false, false);
439 
440         return ctx.search(baseDN, userFilter, cons);
441     }
442 
443     public static String getUsersDN(long companyId) throws Exception {
444         return PrefsPropsUtil.getString(companyId, PropsUtil.LDAP_USERS_DN);
445     }
446 
447     public static boolean hasUser(long companyId, String screenName)
448         throws Exception {
449 
450         if (getUser(companyId, screenName) != null) {
451             return true;
452         }
453         else {
454             return false;
455         }
456     }
457 
458     public static void importFromLDAP() throws Exception {
459         List companies = CompanyLocalServiceUtil.getCompanies();
460 
461         for (int i = 0; i < companies.size(); i++) {
462             Company company = (Company)companies.get(i);
463 
464             importFromLDAP(company.getCompanyId());
465         }
466     }
467 
468     public static void importFromLDAP(long companyId) throws Exception {
469         if (!isImportEnabled(companyId)) {
470             return;
471         }
472 
473         LdapContext ctx = getContext(companyId);
474 
475         if (ctx == null) {
476             return;
477         }
478 
479         try {
480             String importMethod = PrefsPropsUtil.getString(
481                 companyId, PropsUtil.LDAP_IMPORT_METHOD);
482 
483             if (importMethod.equals(IMPORT_BY_USER)) {
484                 NamingEnumeration enu = getUsers(companyId, ctx, 0);
485 
486                 // Loop through all LDAP users
487 
488                 while (enu.hasMore()) {
489                     SearchResult result = (SearchResult)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 enu = getGroups(companyId, ctx, 0);
500 
501                 // Loop through all LDAP groups
502 
503                 while (enu.hasMore()) {
504                     SearchResult result = (SearchResult)enu.next();
505 
506                     Attributes attrs = getAttributes(
507                         ctx, getNameInNamespace(companyId, result));
508 
509                     importLDAPGroup(companyId, ctx, attrs, true);
510                 }
511             }
512         }
513         catch (Exception e) {
514             _log.error("Error importing LDAP users and groups", e);
515         }
516         finally {
517             if (ctx != null) {
518                 ctx.close();
519             }
520         }
521     }
522 
523     public static UserGroup importLDAPGroup(
524             long companyId, LdapContext ctx, Attributes attrs,
525             boolean importGroupMembership)
526         throws Exception {
527 
528         AttributesTransformer attrsTransformer =
529             AttributesTransformerFactory.getInstance();
530 
531         attrs = attrsTransformer.transformGroup(attrs);
532 
533         Properties groupMappings = getGroupMappings(companyId);
534 
535         LogUtil.debug(_log, groupMappings);
536 
537         String groupName = LDAPUtil.getAttributeValue(
538             attrs, groupMappings.getProperty("groupName")).toLowerCase();
539         String description = LDAPUtil.getAttributeValue(
540             attrs, groupMappings.getProperty("description"));
541 
542         // Get or create user group
543 
544         UserGroup userGroup = null;
545 
546         try {
547             userGroup = UserGroupLocalServiceUtil.getUserGroup(
548                 companyId, groupName);
549 
550             UserGroupLocalServiceUtil.updateUserGroup(
551                 companyId, userGroup.getUserGroupId(), groupName, description);
552         }
553         catch (NoSuchUserGroupException nsuge) {
554             if (_log.isDebugEnabled()) {
555                 _log.debug("Adding user group to portal " + groupName);
556             }
557 
558             long defaultUserId = UserLocalServiceUtil.getDefaultUserId(
559                 companyId);
560 
561             try {
562                 userGroup = UserGroupLocalServiceUtil.addUserGroup(
563                     defaultUserId, companyId, groupName, description);
564             }
565             catch (Exception e) {
566                 if (_log.isWarnEnabled()) {
567                     _log.warn("Could not create user group " + groupName);
568                 }
569 
570                 if (_log.isDebugEnabled()) {
571                     _log.debug(e, e);
572                 }
573             }
574         }
575 
576         // Import users and membership
577 
578         if (importGroupMembership && (userGroup != null)) {
579             Attribute attr = attrs.get(groupMappings.getProperty("user"));
580 
581             if (attr != null){
582                 _importUsersAndMembershipFromLDAPGroup(
583                     companyId, ctx, userGroup.getUserGroupId(), attr);
584             }
585         }
586 
587         return userGroup;
588     }
589 
590     public static User importLDAPUser(
591             long companyId, LdapContext ctx, Attributes attrs, String password,
592             boolean importGroupMembership)
593         throws Exception {
594 
595         AttributesTransformer attrsTransformer =
596             AttributesTransformerFactory.getInstance();
597 
598         attrs = attrsTransformer.transformUser(attrs);
599 
600         Properties userMappings = getUserMappings(companyId);
601 
602         LogUtil.debug(_log, userMappings);
603 
604         User defaultUser = UserLocalServiceUtil.getDefaultUser(companyId);
605 
606         boolean autoPassword = false;
607         boolean updatePassword = true;
608 
609         if (password.equals(StringPool.BLANK)) {
610             autoPassword = true;
611             updatePassword = false;
612         }
613 
614         long creatorUserId = 0;
615         boolean passwordReset = false;
616         boolean autoScreenName = false;
617         String screenName = LDAPUtil.getAttributeValue(
618             attrs, userMappings.getProperty("screenName")).toLowerCase();
619         String emailAddress = LDAPUtil.getAttributeValue(
620             attrs, userMappings.getProperty("emailAddress"));
621         Locale locale = defaultUser.getLocale();
622         String firstName = LDAPUtil.getAttributeValue(
623             attrs, userMappings.getProperty("firstName"));
624         String middleName = LDAPUtil.getAttributeValue(
625             attrs, userMappings.getProperty("middleName"));
626         String lastName = LDAPUtil.getAttributeValue(
627             attrs, userMappings.getProperty("lastName"));
628 
629         if (Validator.isNull(firstName) || Validator.isNull(lastName)) {
630             String fullName = LDAPUtil.getAttributeValue(
631                 attrs, userMappings.getProperty("fullName"));
632 
633             String[] names = LDAPUtil.splitFullName(fullName);
634 
635             firstName = names[0];
636             middleName = names[1];
637             lastName = names[2];
638         }
639 
640         int prefixId = 0;
641         int suffixId = 0;
642         boolean male = true;
643         int birthdayMonth = Calendar.JANUARY;
644         int birthdayDay = 1;
645         int birthdayYear = 1970;
646         String jobTitle = LDAPUtil.getAttributeValue(
647             attrs, userMappings.getProperty("jobTitle"));
648         long[] organizationIds = new long[0];
649         boolean sendEmail = false;
650 
651         if (_log.isDebugEnabled()) {
652             _log.debug(
653                 "Screen name " + screenName + " and email address " +
654                     emailAddress);
655         }
656 
657         if (Validator.isNull(screenName) || Validator.isNull(emailAddress)) {
658             if (_log.isWarnEnabled()) {
659                 _log.warn(
660                     "Cannot add user because screen name and email address " +
661                         "are required");
662             }
663 
664             return null;
665         }
666 
667         User user = null;
668 
669         try {
670 
671             // Find corresponding portal user
672 
673             String authType = PrefsPropsUtil.getString(
674                 companyId, PropsUtil.COMPANY_SECURITY_AUTH_TYPE,
675                 PropsValues.COMPANY_SECURITY_AUTH_TYPE);
676 
677             if (authType.equals(CompanyImpl.AUTH_TYPE_SN)) {
678                 user = UserLocalServiceUtil.getUserByScreenName(
679                     companyId, screenName);
680             }
681             else {
682                 user = UserLocalServiceUtil.getUserByEmailAddress(
683                     companyId, emailAddress);
684             }
685 
686             // Skip if is default user
687 
688             if (user.isDefaultUser()) {
689                 return user;
690             }
691 
692             // Skip import if user fields has been already synced and if
693             // import is part of a scheduled import
694 
695             Date ldapUserModifiedDate = null;
696 
697             String modifiedDate = LDAPUtil.getAttributeValue(
698                 attrs, "modifyTimestamp");
699 
700             try {
701                 DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
702 
703                 ldapUserModifiedDate = dateFormat.parse(modifiedDate);
704 
705                 if (ldapUserModifiedDate.equals(user.getModifiedDate()) &&
706                     autoPassword) {
707 
708                     if (_log.isDebugEnabled()) {
709                         _log.debug(
710                             "User is already syncronized, skipping user " +
711                                 user.getEmailAddress());
712                     }
713 
714                     return user;
715                 }
716             }
717             catch (ParseException pe) {
718                 if (_log.isDebugEnabled()) {
719                     _log.debug(
720                         "Unable to parse LDAP modify timestamp " +
721                             modifiedDate);
722                 }
723 
724                 _log.debug(pe, pe);
725             }
726 
727             Contact contact = user.getContact();
728 
729             Calendar birthdayCal = CalendarFactoryUtil.getCalendar();
730 
731             birthdayCal.setTime(contact.getBirthday());
732 
733             birthdayMonth = birthdayCal.get(Calendar.MONTH);
734             birthdayDay = birthdayCal.get(Calendar.DATE);
735             birthdayYear = birthdayCal.get(Calendar.YEAR);
736 
737             // User exists so update user information
738 
739             if (updatePassword) {
740                 user = UserLocalServiceUtil.updatePassword(
741                     user.getUserId(), password, password, passwordReset,
742                     true);
743             }
744 
745             user = UserLocalServiceUtil.updateUser(
746                 user.getUserId(), password, user.isPasswordReset(), screenName,
747                 emailAddress, user.getLanguageId(), user.getTimeZoneId(),
748                 user.getGreeting(), user.getComments(), firstName, middleName,
749                 lastName, contact.getPrefixId(), contact.getSuffixId(),
750                 contact.getMale(), birthdayMonth, birthdayDay, birthdayYear,
751                 contact.getSmsSn(), contact.getAimSn(), contact.getIcqSn(),
752                 contact.getJabberSn(), contact.getMsnSn(), contact.getSkypeSn(),
753                 contact.getYmSn(), jobTitle, user.getOrganizationIds());
754 
755             if (ldapUserModifiedDate != null) {
756                 UserLocalServiceUtil.updateModifiedDate(
757                     user.getUserId(), ldapUserModifiedDate);
758             }
759         }
760         catch (NoSuchUserException nsue) {
761 
762             // User does not exist so create
763 
764         }
765 
766         if (user == null) {
767             try {
768                 if (_log.isDebugEnabled()) {
769                     _log.debug("Adding user to portal " + emailAddress);
770                 }
771 
772                 user = UserLocalServiceUtil.addUser(
773                     creatorUserId, companyId, autoPassword, password, password,
774                     autoScreenName, screenName, emailAddress, locale, firstName,
775                     middleName, lastName, prefixId, suffixId, male,
776                     birthdayMonth, birthdayDay, birthdayYear, jobTitle,
777                     organizationIds, sendEmail);
778             }
779             catch (Exception e){
780                 _log.error(
781                     "Problem adding user with screen name " + screenName +
782                         " and email address " + emailAddress,
783                     e);
784             }
785         }
786 
787         // Import user groups and membership
788 
789         if (importGroupMembership && (user != null)) {
790             String userMappingsGroup = userMappings.getProperty("group");
791 
792             if (userMappingsGroup != null) {
793                 Attribute attr = attrs.get(userMappingsGroup);
794 
795                 if (attr != null){
796                     _importGroupsAndMembershipFromLDAPUser(
797                         companyId, ctx, user.getUserId(), attr);
798                 }
799             }
800         }
801 
802         return user;
803     }
804 
805     public static boolean isAuthEnabled(long companyId)
806         throws PortalException, SystemException {
807 
808         if (PrefsPropsUtil.getBoolean(
809                 companyId, PropsUtil.LDAP_AUTH_ENABLED,
810                 PropsValues.LDAP_AUTH_ENABLED)) {
811 
812             return true;
813         }
814         else {
815             return false;
816         }
817     }
818 
819     public static boolean isExportEnabled(long companyId)
820         throws PortalException, SystemException {
821 
822         if (PrefsPropsUtil.getBoolean(
823                 companyId, PropsUtil.LDAP_EXPORT_ENABLED,
824                 PropsValues.LDAP_EXPORT_ENABLED)) {
825 
826             return true;
827         }
828         else {
829             return false;
830         }
831     }
832 
833     public static boolean isImportEnabled(long companyId)
834         throws PortalException, SystemException {
835 
836         if (PrefsPropsUtil.getBoolean(
837                 companyId, PropsUtil.LDAP_IMPORT_ENABLED,
838                 PropsValues.LDAP_IMPORT_ENABLED)) {
839 
840             return true;
841         }
842         else {
843             return false;
844         }
845     }
846 
847     public static boolean isImportOnStartup(long companyId)
848         throws PortalException, SystemException {
849 
850         if (PrefsPropsUtil.getBoolean(
851                 companyId, PropsUtil.LDAP_IMPORT_ON_STARTUP)) {
852 
853             return true;
854         }
855         else {
856             return false;
857         }
858     }
859 
860     public static boolean isNtlmEnabled(long companyId)
861         throws PortalException, SystemException {
862 
863         if (!isAuthEnabled(companyId)) {
864             return false;
865         }
866 
867         if (PrefsPropsUtil.getBoolean(companyId, PropsUtil.NTLM_AUTH_ENABLED)) {
868             return true;
869         }
870         else {
871             return false;
872         }
873     }
874 
875     public static boolean isPasswordPolicyEnabled(long companyId)
876         throws PortalException, SystemException {
877 
878         if (PrefsPropsUtil.getBoolean(
879                 companyId, PropsUtil.LDAP_PASSWORD_POLICY_ENABLED,
880                 PropsValues.LDAP_PASSWORD_POLICY_ENABLED)) {
881 
882             return true;
883         }
884         else {
885             return false;
886         }
887     }
888 
889     private static void _importGroupsAndMembershipFromLDAPUser(
890             long companyId, LdapContext ctx, long userId, Attribute attr)
891         throws Exception {
892 
893         // Remove all user group membership from user
894 
895         UserGroupLocalServiceUtil.clearUserUserGroups(userId);
896 
897         for (int i = 0; i < attr.size(); i++) {
898 
899             // Find group in LDAP
900 
901             String fullGroupDN = (String)attr.get(i);
902 
903             Attributes groupAttrs = null;
904 
905             try {
906                 groupAttrs = getAttributes(ctx, fullGroupDN);
907             }
908             catch (NameNotFoundException nnfe) {
909                 _log.error(
910                     "LDAP group not found with fullGroupDN " + fullGroupDN);
911 
912                 _log.error(nnfe, nnfe);
913 
914                 continue;
915             }
916 
917             UserGroup userGroup = importLDAPGroup(
918                 companyId, ctx, groupAttrs, false);
919 
920             // Add user to user group
921 
922             if (userGroup != null) {
923                 if (_log.isDebugEnabled()) {
924                     _log.debug(
925                         "Adding " + userId + " to group " +
926                             userGroup.getUserGroupId());
927                 }
928 
929                 UserLocalServiceUtil.addUserGroupUsers(
930                     userGroup.getUserGroupId(), new long[] {userId});
931             }
932         }
933     }
934 
935     private static void _importUsersAndMembershipFromLDAPGroup(
936             long companyId, LdapContext ctx, long userGroupId, Attribute attr)
937         throws Exception {
938 
939         // Remove all user membership from user group
940 
941         UserLocalServiceUtil.clearUserGroupUsers(userGroupId);
942 
943         for (int i = 0; i < attr.size(); i++) {
944 
945             // Find user in LDAP
946 
947             String fullUserDN = (String)attr.get(i);
948 
949             Attributes userAttrs = null;
950 
951             try {
952                 userAttrs = getAttributes(ctx, fullUserDN);
953             }
954             catch (NameNotFoundException nnfe) {
955                 _log.error(
956                     "LDAP user not found with fullUserDN " + fullUserDN);
957 
958                 _log.error(nnfe, nnfe);
959 
960                 continue;
961             }
962 
963             User user = importLDAPUser(
964                 companyId, ctx, userAttrs, StringPool.BLANK, false);
965 
966             // Add user to user group
967 
968             if (user != null) {
969                 if (_log.isDebugEnabled()) {
970                     _log.debug(
971                         "Adding " + user.getUserId() + " to group " +
972                             userGroupId);
973                 }
974 
975                 UserLocalServiceUtil.addUserGroupUsers(
976                     userGroupId, new long[] {user.getUserId()});
977             }
978         }
979     }
980 
981     private static Log _log = LogFactoryUtil.getLog(PortalLDAPUtil.class);
982 
983 }