1
14
15 package com.liferay.portal.security.ldap;
16
17 import com.liferay.portal.SystemException;
18 import com.liferay.portal.kernel.log.Log;
19 import com.liferay.portal.kernel.log.LogFactoryUtil;
20 import com.liferay.portal.kernel.log.LogUtil;
21 import com.liferay.portal.kernel.util.GetterUtil;
22 import com.liferay.portal.kernel.util.PropsKeys;
23 import com.liferay.portal.kernel.util.StringBundler;
24 import com.liferay.portal.kernel.util.StringPool;
25 import com.liferay.portal.kernel.util.StringUtil;
26 import com.liferay.portal.kernel.util.Validator;
27 import com.liferay.portal.model.Contact;
28 import com.liferay.portal.model.User;
29 import com.liferay.portal.model.UserGroup;
30 import com.liferay.portal.util.PrefsPropsUtil;
31 import com.liferay.portal.util.PropsValues;
32
33 import java.util.ArrayList;
34 import java.util.List;
35 import java.util.Properties;
36
37 import javax.naming.Binding;
38 import javax.naming.CompositeName;
39 import javax.naming.Context;
40 import javax.naming.Name;
41 import javax.naming.NamingEnumeration;
42 import javax.naming.OperationNotSupportedException;
43 import javax.naming.directory.Attribute;
44 import javax.naming.directory.Attributes;
45 import javax.naming.directory.SearchControls;
46 import javax.naming.directory.SearchResult;
47 import javax.naming.ldap.Control;
48 import javax.naming.ldap.InitialLdapContext;
49 import javax.naming.ldap.LdapContext;
50 import javax.naming.ldap.PagedResultsControl;
51 import javax.naming.ldap.PagedResultsResponseControl;
52
53
65 public class PortalLDAPUtil {
66
67
70 public static final String IMPORT_BY_GROUP =
71 PortalLDAPImporter.IMPORT_BY_GROUP;
72
73
76 public static final String IMPORT_BY_USER =
77 PortalLDAPImporter.IMPORT_BY_USER;
78
79
82 public static void exportToLDAP(Contact contact) throws Exception {
83 PortalLDAPExporter.exportToLDAP(contact);
84 }
85
86
89 public static void exportToLDAP(User user) throws Exception {
90 PortalLDAPExporter.exportToLDAP(user);
91 }
92
93
97 public static String getAuthSearchFilter(
98 long ldapServerId, long companyId, String emailAddress,
99 String screenName, String userId)
100 throws SystemException {
101
102 return LDAPSettingsUtil.getAuthSearchFilter(
103 ldapServerId, companyId, emailAddress, screenName, userId);
104 }
105
106 public static LdapContext getContext(long ldapServerId, long companyId)
107 throws Exception {
108
109 String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
110
111 String baseProviderURL = PrefsPropsUtil.getString(
112 companyId, PropsKeys.LDAP_BASE_PROVIDER_URL + postfix);
113 String pricipal = PrefsPropsUtil.getString(
114 companyId, PropsKeys.LDAP_SECURITY_PRINCIPAL + postfix);
115 String credentials = PrefsPropsUtil.getString(
116 companyId, PropsKeys.LDAP_SECURITY_CREDENTIALS + postfix);
117
118 return getContext(companyId, baseProviderURL, pricipal, credentials);
119 }
120
121 public static LdapContext getContext(
122 long companyId, String providerURL, String principal,
123 String credentials)
124 throws Exception {
125
126 Properties env = new Properties();
127
128 env.put(
129 Context.INITIAL_CONTEXT_FACTORY,
130 PrefsPropsUtil.getString(
131 companyId, PropsKeys.LDAP_FACTORY_INITIAL));
132 env.put(Context.PROVIDER_URL, providerURL);
133 env.put(Context.SECURITY_PRINCIPAL, principal);
134 env.put(Context.SECURITY_CREDENTIALS, credentials);
135 env.put(
136 Context.REFERRAL,
137 PrefsPropsUtil.getString(companyId, PropsKeys.LDAP_REFERRAL));
138
139
141 env.put("com.sun.jndi.ldap.connect.pool", "true");
142 env.put("com.sun.jndi.ldap.connect.pool.maxsize","50");
143 env.put("com.sun.jndi.ldap.connect.pool.timeout", "10000");
144
145 LogUtil.debug(_log, env);
146
147 LdapContext ldapContext = null;
148
149 try {
150 ldapContext = new InitialLdapContext(env, null);
151 }
152 catch (Exception e) {
153 if (_log.isWarnEnabled()) {
154 _log.warn("Failed to bind to the LDAP server");
155 }
156
157 if (_log.isDebugEnabled()) {
158 _log.debug(e, e);
159 }
160 }
161
162 return ldapContext;
163 }
164
165 public static Attributes getGroupAttributes(
166 long ldapServerId, long companyId, LdapContext ldapContext,
167 String fullDistinguishedName)
168 throws Exception {
169
170 return getGroupAttributes(ldapServerId, companyId, ldapContext,
171 fullDistinguishedName, false);
172 }
173
174 public static Attributes getGroupAttributes(
175 long ldapServerId, long companyId, LdapContext ldapContext,
176 String fullDistinguishedName, boolean includeReferenceAttributes)
177 throws Exception {
178
179 Properties groupMappings = LDAPSettingsUtil.getGroupMappings(
180 ldapServerId, companyId);
181
182 List<String> mappedGroupAttributeIds = new ArrayList<String>();
183
184 mappedGroupAttributeIds.add(groupMappings.getProperty("groupName"));
185 mappedGroupAttributeIds.add(groupMappings.getProperty("description"));
186
187 if (includeReferenceAttributes) {
188 mappedGroupAttributeIds.add(groupMappings.getProperty("user"));
189 }
190
191 return _getAttributes(
192 ldapContext, fullDistinguishedName,
193 mappedGroupAttributeIds.toArray(new String[0]));
194 }
195
196
199 public static Properties getGroupMappings(long ldapServerId, long companyId)
200 throws Exception {
201
202 return LDAPSettingsUtil.getGroupMappings(ldapServerId, companyId);
203 }
204
205 public static List<SearchResult> getGroups(
206 long companyId, LdapContext ldapContext, int maxResults,
207 String baseDN, String groupFilter)
208 throws Exception {
209
210 return searchLDAP(
211 companyId, ldapContext, maxResults, baseDN, groupFilter, null);
212 }
213
214 public static List<SearchResult> getGroups(
215 long ldapServerId, long companyId, LdapContext ldapContext,
216 int maxResults)
217 throws Exception {
218
219 String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
220
221 String baseDN = PrefsPropsUtil.getString(
222 companyId, PropsKeys.LDAP_BASE_DN + postfix);
223 String groupFilter = PrefsPropsUtil.getString(
224 companyId, PropsKeys.LDAP_IMPORT_GROUP_SEARCH_FILTER + postfix);
225
226 return getGroups(
227 companyId, ldapContext, maxResults, baseDN, groupFilter);
228 }
229
230 public static long getLdapServerId(long companyId, String screenName)
231 throws Exception {
232
233 long[] ldapServerIds = StringUtil.split(
234 PrefsPropsUtil.getString(companyId, "ldap.server.ids"), 0L);
235
236 for (long ldapServerId : ldapServerIds) {
237 if (hasUser(ldapServerId, companyId, screenName)) {
238 return ldapServerId;
239 }
240 }
241
242 if (ldapServerIds.length > 0) {
243 return ldapServerIds[0];
244 }
245
246 return 0;
247 }
248
249 public static Attribute getMultivaluedAttribute(
250 long companyId, LdapContext ldapContext, String baseDN,
251 String filter, Attribute attribute)
252 throws Exception {
253
254 if (attribute.size() > 0) {
255 return attribute;
256 }
257
258 String[] attributeIds = {_getNextRange(attribute.getID())};
259
260 while (true) {
261 List<SearchResult> searchResults = searchLDAP(
262 companyId, ldapContext, 0, baseDN, filter, attributeIds);
263
264 if (searchResults.size() != 1) {
265 break;
266 }
267
268 SearchResult searchResult = searchResults.get(0);
269
270 Attributes attributes = searchResult.getAttributes();
271
272 if (attributes.size() != 1) {
273 break;
274 }
275
276 NamingEnumeration<? extends Attribute> enu = attributes.getAll();
277
278 if (!enu.hasMoreElements()) {
279 break;
280 }
281
282 Attribute curAttribute = enu.nextElement();
283
284 for (int i = 0; i < curAttribute.size(); i++) {
285 attribute.add(curAttribute.get(i));
286 }
287
288 if (StringUtil.endsWith(curAttribute.getID(), StringPool.STAR) ||
289 (curAttribute.size() < PropsValues.LDAP_RANGE_SIZE)) {
290
291 break;
292 }
293
294 attributeIds[0] = _getNextRange(attributeIds[0]);
295 }
296
297 return attribute;
298 }
299
300 public static String getNameInNamespace(
301 long ldapServerId, long companyId, Binding binding)
302 throws Exception {
303
304 String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
305
306 String baseDN = PrefsPropsUtil.getString(
307 companyId, PropsKeys.LDAP_BASE_DN + postfix);
308
309 String name = binding.getName();
310
311 if (name.startsWith(StringPool.QUOTE) &&
312 name.endsWith(StringPool.QUOTE)) {
313
314 name = name.substring(1, name.length() - 1);
315 }
316
317 if (Validator.isNull(baseDN)) {
318 return name.toString();
319 }
320 else {
321 return name.concat(StringPool.COMMA).concat(baseDN);
322 }
323 }
324
325 public static Binding getUser(
326 long ldapServerId, long companyId, String screenName)
327 throws Exception {
328
329 String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
330
331 LdapContext ldapContext = getContext(ldapServerId, companyId);
332
333 NamingEnumeration<SearchResult> enu = null;
334
335 try {
336 if (ldapContext == null) {
337 return null;
338 }
339
340 String baseDN = PrefsPropsUtil.getString(
341 companyId, PropsKeys.LDAP_BASE_DN + postfix);
342
343 Properties userMappings = LDAPSettingsUtil.getUserMappings(
344 ldapServerId, companyId);
345
346 StringBundler filter = new StringBundler(5);
347
348 filter.append(StringPool.OPEN_PARENTHESIS);
349 filter.append(userMappings.getProperty("screenName"));
350 filter.append(StringPool.EQUAL);
351 filter.append(screenName);
352 filter.append(StringPool.CLOSE_PARENTHESIS);
353
354 SearchControls cons = new SearchControls(
355 SearchControls.SUBTREE_SCOPE, 1, 0, null, false, false);
356
357 enu = ldapContext.search(baseDN, filter.toString(), cons);
358 }
359 catch (Exception e) {
360 throw e;
361 }
362 finally {
363 if (ldapContext != null) {
364 ldapContext.close();
365 }
366 }
367
368 if (enu.hasMoreElements()) {
369 Binding binding = enu.nextElement();
370
371 enu.close();
372
373 return binding;
374 }
375 else {
376 return null;
377 }
378 }
379
380 public static Attributes getUserAttributes(
381 long ldapServerId, long companyId, LdapContext ldapContext,
382 String fullDistinguishedName)
383 throws Exception {
384
385 Properties userMappings = LDAPSettingsUtil.getUserMappings(
386 ldapServerId, companyId);
387
388 String[] mappedUserAttributeIds = {
389 userMappings.getProperty("screenName"),
390 userMappings.getProperty("emailAddress"),
391 userMappings.getProperty("fullName"),
392 userMappings.getProperty("firstName"),
393 userMappings.getProperty("middleName"),
394 userMappings.getProperty("lastName"),
395 userMappings.getProperty("jobTitle"),
396 userMappings.getProperty("group")
397 };
398
399 return _getAttributes(
400 ldapContext, fullDistinguishedName, mappedUserAttributeIds);
401 }
402
403
406 public static Properties getUserMappings(long ldapServerId, long companyId)
407 throws Exception {
408
409 return LDAPSettingsUtil.getUserMappings(ldapServerId, companyId);
410 }
411
412 public static List<SearchResult> getUsers(
413 long companyId, LdapContext ldapContext, int maxResults,
414 String baseDN, String userFilter)
415 throws Exception {
416
417 return searchLDAP(
418 companyId, ldapContext, maxResults, baseDN, userFilter, null);
419 }
420
421 public static List<SearchResult> getUsers(
422 long ldapServerId, long companyId, LdapContext ldapContext,
423 int maxResults)
424 throws Exception {
425
426 String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
427
428 String baseDN = PrefsPropsUtil.getString(
429 companyId, PropsKeys.LDAP_BASE_DN + postfix);
430 String userFilter = PrefsPropsUtil.getString(
431 companyId, PropsKeys.LDAP_IMPORT_USER_SEARCH_FILTER + postfix);
432
433 return getUsers(companyId, ldapContext, maxResults, baseDN, userFilter);
434 }
435
436 public static String getUsersDN(long ldapServerId, long companyId)
437 throws Exception {
438
439 String postfix = LDAPSettingsUtil.getPropertyPostfix(ldapServerId);
440
441 return PrefsPropsUtil.getString(
442 companyId, PropsKeys.LDAP_USERS_DN + postfix);
443 }
444
445 public static boolean hasUser(
446 long ldapServerId, long companyId, String screenName)
447 throws Exception {
448
449 if (getUser(ldapServerId, companyId, screenName) != null) {
450 return true;
451 }
452 else {
453 return false;
454 }
455 }
456
457
460 public static void importFromLDAP() throws Exception {
461 PortalLDAPImporter.importFromLDAP();
462 }
463
464
467 public static void importFromLDAP(long companyId) throws Exception {
468 PortalLDAPImporter.importFromLDAP(companyId);
469 }
470
471
474 public static void importFromLDAP(long ldapServerId, long companyId)
475 throws Exception {
476
477 PortalLDAPImporter.importFromLDAP(ldapServerId, companyId);
478 }
479
480
484 public static UserGroup importLDAPGroup(
485 long ldapServerId, long companyId, LdapContext ldapContext,
486 Attributes attributes, boolean importGroupMembership)
487 throws Exception {
488
489 return PortalLDAPImporter.importLDAPGroup(
490 ldapServerId, companyId, ldapContext, attributes,
491 importGroupMembership);
492 }
493
494
498 public static User importLDAPUser(
499 long ldapServerId, long companyId, LdapContext ldapContext,
500 Attributes attributes, String password,
501 boolean importGroupMembership)
502 throws Exception {
503
504 return PortalLDAPImporter.importLDAPUser(
505 ldapServerId, companyId, ldapContext, attributes, password,
506 importGroupMembership);
507 }
508
509
512 public static boolean isAuthEnabled(long companyId) throws SystemException {
513 return LDAPSettingsUtil.isAuthEnabled(companyId);
514 }
515
516
519 public static boolean isExportEnabled(long companyId)
520 throws SystemException {
521
522 return LDAPSettingsUtil.isExportEnabled(companyId);
523 }
524
525
528 public static boolean isImportEnabled(long companyId)
529 throws SystemException {
530
531 return LDAPSettingsUtil.isImportEnabled(companyId);
532 }
533
534
537 public static boolean isImportOnStartup(long companyId)
538 throws SystemException {
539
540 return LDAPSettingsUtil.isImportOnStartup(companyId);
541 }
542
543
546 public static boolean isNtlmEnabled(long companyId)
547 throws SystemException {
548
549 return LDAPSettingsUtil.isNtlmEnabled(companyId);
550 }
551
552
555 public static boolean isPasswordPolicyEnabled(long companyId)
556 throws SystemException {
557
558 return LDAPSettingsUtil.isPasswordPolicyEnabled(companyId);
559 }
560
561
564 public static boolean isSiteMinderEnabled(long companyId)
565 throws SystemException {
566
567 return LDAPSettingsUtil.isSiteMinderEnabled(companyId);
568 }
569
570 public static List<SearchResult> searchLDAP(
571 long companyId, LdapContext ldapContext, int maxResults,
572 String baseDN, String filter, String[] attributeIds)
573 throws Exception {
574
575 List<SearchResult> searchResults = new ArrayList<SearchResult>();
576
577 SearchControls cons = new SearchControls(
578 SearchControls.SUBTREE_SCOPE, maxResults, 0, attributeIds, false,
579 false);
580
581 try {
582 byte[] cookie = new byte[0];
583
584 while (cookie != null) {
585 if (cookie.length == 0) {
586 ldapContext.setRequestControls(
587 new Control[] {
588 new PagedResultsControl(
589 PropsValues.LDAP_PAGE_SIZE, Control.CRITICAL)
590 });
591 }
592 else {
593 ldapContext.setRequestControls(
594 new Control[] {
595 new PagedResultsControl(
596 PropsValues.LDAP_PAGE_SIZE, cookie,
597 Control.CRITICAL)
598 });
599 }
600
601 NamingEnumeration<SearchResult> enu = ldapContext.search(
602 baseDN, filter, cons);
603
604 while (enu.hasMoreElements()) {
605 searchResults.add(enu.nextElement());
606 }
607
608 enu.close();
609
610 cookie = _getCookie(ldapContext.getResponseControls());
611 }
612 }
613 catch (OperationNotSupportedException onse) {
614 ldapContext.setRequestControls(null);
615
616 NamingEnumeration<SearchResult> enu = ldapContext.search(
617 baseDN, filter, cons);
618
619 while (enu.hasMoreElements()) {
620 searchResults.add(enu.nextElement());
621 }
622
623 enu.close();
624 }
625 finally {
626 ldapContext.setRequestControls(null);
627 }
628
629 return searchResults;
630 }
631
632 private static Attributes _getAttributes(
633 LdapContext ldapContext, String fullDistinguishedName,
634 String[] attributeIds)
635 throws Exception {
636
637 Name fullDN = new CompositeName().add(fullDistinguishedName);
638
639 Attributes attributes = null;
640
641 String[] auditAttributeIds = {
642 "creatorsName", "createTimestamp", "modifiersName",
643 "modifyTimestamp"
644 };
645
646 if (attributeIds == null) {
647
648
650 attributes = ldapContext.getAttributes(fullDN);
651
652 NamingEnumeration<? extends Attribute> enu =
653 ldapContext.getAttributes(fullDN, auditAttributeIds).getAll();
654
655 while (enu.hasMoreElements()) {
656 attributes.put(enu.nextElement());
657 }
658
659 enu.close();
660 }
661 else {
662
663
665 int attributeCount = attributeIds.length + auditAttributeIds.length;
666
667 String[] allAttributeIds = new String[attributeCount];
668
669 System.arraycopy(
670 attributeIds, 0, allAttributeIds, 0, attributeIds.length);
671 System.arraycopy(
672 auditAttributeIds, 0, allAttributeIds, attributeIds.length,
673 auditAttributeIds.length);
674
675 attributes = ldapContext.getAttributes(fullDN, allAttributeIds);
676 }
677
678 return attributes;
679 }
680
681 private static byte[] _getCookie(Control[] controls) {
682 if (controls == null) {
683 return null;
684 }
685
686 for (Control control : controls) {
687 if (control instanceof PagedResultsResponseControl) {
688 PagedResultsResponseControl pagedResultsResponseControl =
689 (PagedResultsResponseControl)control;
690
691 return pagedResultsResponseControl.getCookie();
692 }
693 }
694
695 return null;
696 }
697
698 private static String _getNextRange(String attributeId) {
699 String originalAttributeId = null;
700 int start = 0;
701 int end = 0;
702
703 int x = attributeId.indexOf(StringPool.SEMICOLON);
704
705 if (x < 0) {
706 originalAttributeId = attributeId;
707 end = PropsValues.LDAP_RANGE_SIZE - 1;
708 }
709 else {
710 int y = attributeId.indexOf(StringPool.EQUAL, x);
711 int z = attributeId.indexOf(StringPool.DASH, y);
712
713 originalAttributeId = attributeId.substring(0, x);
714 start = GetterUtil.getInteger(attributeId.substring(y + 1, z));
715 end = GetterUtil.getInteger(attributeId.substring(z + 1));
716
717 start += PropsValues.LDAP_RANGE_SIZE;
718 end += PropsValues.LDAP_RANGE_SIZE;
719 }
720
721 StringBundler sb = new StringBundler(6);
722
723 sb.append(originalAttributeId);
724 sb.append(StringPool.SEMICOLON);
725 sb.append("range=");
726 sb.append(start);
727 sb.append(StringPool.DASH);
728 sb.append(end);
729
730 return sb.toString();
731 }
732
733 private static Log _log = LogFactoryUtil.getLog(PortalLDAPUtil.class);
734
735 }