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