1 41 42 package org.jahia.services.usermanager; 43 44 import org.jahia.data.JahiaDOMObject; 45 import org.jahia.exceptions.JahiaException; 46 import org.jahia.exceptions.JahiaInitializationException; 47 import org.jahia.exceptions.database.JahiaDatabaseException; 48 import org.jahia.registries.ServicesRegistry; 49 import org.jahia.services.cache.Cache; 50 import org.jahia.services.cache.CacheFactory; 51 import org.jahia.services.database.JahiaIncrementorsDBService; 52 import org.jahia.services.sites.JahiaSite; 53 import org.jahia.services.sites.JahiaSiteTools; 54 import org.jahia.settings.SettingsBean; 55 import org.jahia.utils.JahiaTools; 56 57 import javax.naming.*; 58 import javax.naming.directory.*; 59 import java.io.File ; 60 import java.io.FileInputStream ; 61 import java.io.FileNotFoundException ; 62 import java.io.IOException ; 63 import java.sql.Connection ; 64 import java.sql.ResultSet ; 65 import java.sql.SQLException ; 66 import java.sql.Statement ; 67 import java.util.*; 68 69 70 79 80 public class JahiaGroupManagerLDAPProvider extends JahiaGroupManagerProvider { 81 82 83 private static org.apache.log4j.Logger logger = 84 org.apache.log4j.Logger.getLogger (JahiaGroupManagerLDAPProvider.class); 85 86 private final String MSG_INTERNAL_ERROR = "Group Manager internal error"; 87 88 89 private static JahiaGroupManagerLDAPProvider instance; 90 91 public static final String LDAP_GROUP_CACHE = "LDAPGroupsCache"; 93 94 95 public static final String PROVIDERS_GROUP_CACHE = "ProvidersGroupsCache"; 96 97 private Cache mGroupCache; 98 private Cache mProvidersGroupCache; 99 100 private JahiaIncrementorsDBService mIncrementorService = null; 101 public static final String USERS_GROUPNAME = null; 102 public static final String ADMINISTRATORS_GROUPNAME = null; 103 public static final String GUEST_GROUPNAME = null; 104 105 public static final String PROVIDER_NAME = "ldap"; 106 107 private static String DEFAULT_CONFIGURATION_FILE = "groups.ldap.properties"; 108 109 private static String CONTEXT_FACTORY_PROP = "groups.ldap.context.factory"; 110 private static String LDAP_URL_PROP = "groups.ldap.url"; 111 private static String AUTHENTIFICATION_MODE_PROP = "groups.ldap.authentification.mode"; 112 private static String PUBLIC_BIND_DN_PROP = "groups.ldap.public.bind.dn"; 113 private static String PUBLIC_BIND_PASSWORD_PROP = "groups.ldap.public.bind.password"; 114 115 private static String PRELOAD_GROUP_MEMBERS = "groups.ldap.preload"; 116 117 private static String SEARCH_ATTRIBUTE_PROP = "groups.ldap.search.attribute"; 118 private static String SEARCH_NAME_PROP = "groups.ldap.search.name"; 119 private static String GROUP_OBJECTCLASS_ATTRIBUTE = "groups.ldap.search.objectclass"; 120 private static String DYNGROUP_OBJECTCLASS_ATTRIBUTE = "groups.ldap.dynamic.search.objectclass"; 121 122 private static String SEARCH_COUNT_LIMIT_PROP = "groups.ldap.search.countlimit"; 123 private static String SEARCH_WILDCARD_ATTRIBUTE_LIST = "groups.ldap.search.wildcards.attributes"; 124 125 private static String GROUP_MEMBERS_ATTRIBUTE = "groups.ldap.members.attribute"; 126 private static String DYNGROUP_MEMBERS_ATTRIBUTE = "groups.ldap.dynamic.members.attribute"; 127 128 private static String LDAP_REFFERAL_PROP = "groups.ldap.refferal"; 129 130 134 private static String SEARCH_USER_ATTRIBUTE_NAME = "groups.ldap.members.user.attibute.map"; 135 136 private Properties ldapProperties = null; 137 138 private DirContext publicCtx = null; 139 private boolean connectedToPublic = false; 140 private Vector searchWildCardAttributeList = null; 141 142 private Vector nonExistentGroups = null; 144 145 private JahiaUserManagerLDAPProvider userProvider; 147 148 154 protected JahiaGroupManagerLDAPProvider () 155 throws JahiaException { 156 157 mGroupCache = CacheFactory.createCache (LDAP_GROUP_CACHE); 159 mProvidersGroupCache = CacheFactory.createCache(PROVIDERS_GROUP_CACHE); 160 161 nonExistentGroups = new Vector (); 162 nonExistentGroups.add ("administrators"); 163 nonExistentGroups.add ("guest"); 164 nonExistentGroups.add ("users"); 165 166 ServicesRegistry registry = ServicesRegistry.getInstance (); 167 if (registry != null) { 168 mIncrementorService = registry.getJahiaIncrementorsDBService (); 169 if (mIncrementorService == null) { 170 throw new JahiaException (MSG_INTERNAL_ERROR, 171 "Group manager could not get the Incrementors DB Service instance.", 172 JahiaException.SERVICE_ERROR, 173 JahiaException.CRITICAL_SEVERITY); 174 } 175 } else { 176 throw new JahiaException (MSG_INTERNAL_ERROR, 177 "Group manager could not get the Service Registry instance.", 178 JahiaException.REGISTRY_ERROR, 179 JahiaException.CRITICAL_SEVERITY); 180 } 181 } 182 183 188 public static JahiaGroupManagerLDAPProvider getInstance () { 189 if (instance == null) { 190 try { 191 instance = new JahiaGroupManagerLDAPProvider (); 192 193 } catch (JahiaException ex) { 194 logger.warn ( 195 "Could not create an instance of the JahiaGroupManagerLDAPProvider class"); 196 } 197 } 198 return instance; 199 } 200 201 202 210 211 public Vector getAdminGrantedSites (JahiaUser user) 212 throws org.jahia.exceptions.JahiaException { 213 Vector grantedSites = new Vector (); 214 Enumeration sitesList = ServicesRegistry.getInstance (). 215 getJahiaSitesService ().getSites (); 216 217 while (sitesList.hasMoreElements ()) { 218 JahiaSite jahiaSite = (JahiaSite) sitesList.nextElement (); 219 logger.debug ("check granted site " + jahiaSite.getServerName ()); 220 221 if (JahiaSiteTools.getAdminGroup (jahiaSite).isMember (user)) { 222 logger.debug ("granted site for " + jahiaSite.getServerName ()); 223 grantedSites.add (jahiaSite); 224 } 225 } 226 227 return grantedSites; 228 229 } 230 231 239 public JahiaDOMObject getAppRoleGroupsAsDOM (int parm1) 240 throws org.jahia.exceptions.JahiaException { 241 242 throw new java.lang.UnsupportedOperationException ( 243 "Method getAppRoleGroupsAsDOM() not yet implemented."); 244 } 245 246 256 257 public boolean groupExists (int siteID, String name) { 258 return (lookupGroup (siteID, name) != null); 259 } 260 261 266 267 public JahiaGroup getGuestGroup (int siteID) { 268 if (GUEST_GROUPNAME != null) 269 return lookupGroup (siteID, GUEST_GROUPNAME); 270 else 271 return null; 272 273 } 274 275 283 284 public Vector getGroupnameList (int siteID) { 285 Vector result = new Vector (); 286 287 try { 288 289 NamingEnumeration answer = getGroups (getPublicContext (false), null); 290 while (answer.hasMore ()) { 291 SearchResult sr = (SearchResult) answer.next (); 292 JahiaGroup curGroup = ldapToJahiaGroup (sr); 293 if (curGroup != null) { 294 result.add (curGroup.getGroupname ()); 295 } 296 } 297 } catch (SizeLimitExceededException slee) { 298 logger.debug ("Search generated more than configured maximum search limit in " + 300 DEFAULT_CONFIGURATION_FILE + 301 ", limiting to " + 302 this.ldapProperties.getProperty (SEARCH_COUNT_LIMIT_PROP) + 303 " first results..."); 304 } catch (NamingException ne) { 305 logger.warn ("JNDI warning",ne); 306 invalidatePublicCtx (); 307 result = new Vector (); 308 } 309 310 return result; 311 } 312 313 320 321 public synchronized boolean removeUserFromAllGroups (JahiaUser user) { 322 if (user != null && PROVIDER_NAME.equals(user.getProviderName())) { 323 return false; 324 } 325 return true; 326 } 327 328 337 338 public Vector getUserMembership (JahiaUser user) { 339 if (! (user instanceof JahiaLDAPUser)) { 340 return new Vector(); 341 } 342 343 Vector result = ((JahiaLDAPUser)user).getGroups(); 344 if (result != null) { 345 return result; 346 } 347 348 result = new Vector (); 349 350 StringBuffer filterBuffer = new StringBuffer (); 351 filterBuffer.append ("(&(objectclass="); 352 filterBuffer.append (ldapProperties.getProperty (JahiaGroupManagerLDAPProvider. 353 GROUP_OBJECTCLASS_ATTRIBUTE, "groupOfNames")); 354 filterBuffer.append (")("); 355 filterBuffer.append (ldapProperties.getProperty (GROUP_MEMBERS_ATTRIBUTE)); filterBuffer.append ("="); filterBuffer.append ( ((JahiaLDAPUser) user).getDN() ); filterBuffer.append ("))"); 359 360 SearchControls searchCtl = new SearchControls (); 361 searchCtl.setSearchScope (SearchControls.SUBTREE_SCOPE); 362 String [] retattrs = new String [1]; 363 retattrs[0] = ldapProperties.getProperty (SEARCH_ATTRIBUTE_PROP); 364 searchCtl.setReturningAttributes (retattrs); 365 NamingEnumeration answer = null; 366 try { 367 368 answer = getGroups(getPublicContext (false), searchCtl, filterBuffer); 369 370 while (answer.hasMore ()) { 371 String groupKey = ((SearchResult) answer.nextElement ()). 372 getAttributes (). 373 get (ldapProperties.getProperty ( 374 SEARCH_ATTRIBUTE_PROP)).get (). 375 toString (); 376 result.add ("{ldap}"+groupKey); 377 logger.debug ("groupKey=" + groupKey); 378 } 379 } catch (NamingException e) { 380 logger.warn (e); 381 invalidatePublicCtx (); 382 return new Vector (); 383 } 384 385 filterBuffer = new StringBuffer (); 387 filterBuffer.append ("(objectclass="); 388 filterBuffer.append (ldapProperties.getProperty (JahiaGroupManagerLDAPProvider. 389 DYNGROUP_OBJECTCLASS_ATTRIBUTE, "groupOfURLs")); 390 filterBuffer.append (")"); 391 392 searchCtl = new SearchControls (); 393 searchCtl.setSearchScope (SearchControls.SUBTREE_SCOPE); 394 answer = null; 395 396 try { 397 398 answer = getGroups(getPublicContext (false), searchCtl, filterBuffer); 399 400 while (answer.hasMore ()) { 401 SearchResult sr = (SearchResult) answer.nextElement (); 402 Attributes attr = sr.getAttributes (); 403 String groupKey = attr. 404 get (ldapProperties.getProperty ( 405 SEARCH_ATTRIBUTE_PROP)).get (). 406 toString (); 407 408 logger.debug ("groupKey=" + groupKey); 409 NamingEnumeration answer2 = null; 410 Attribute attribute = attr.get (ldapProperties.getProperty (DYNGROUP_MEMBERS_ATTRIBUTE, "memberurl")); 411 if (attribute != null) { 412 answer2 = attribute.getAll (); 413 while (answer2.hasMore ()) { 414 String url = (String )answer2.next (); 415 Properties p = new Properties(); 416 p.put("ldap.url", url); 417 p.put("user.key", removeKeyPrefix(user.getUserKey())); 418 Set t = getUserManagerProvider().searchUsers(0,p); 419 if (!t.isEmpty()) { 420 result.add("{ldap}"+groupKey); 421 if (answer2.hasMore()) { 422 answer2.close(); 423 } 424 break; 425 } 426 } 427 } 428 } 429 } catch (NamingException e) { 430 logger.warn (e); 431 invalidatePublicCtx (); 432 return new Vector (); 433 } 434 ((JahiaLDAPUser)user).setGroups(result); 435 return result; 436 } 437 438 445 public Vector getGroupList () { 446 Vector result = new Vector (); 447 448 try { 449 450 NamingEnumeration answer = getGroups (getPublicContext (false), null); 451 while (answer.hasMore ()) { 452 SearchResult sr = (SearchResult) answer.next (); 453 JahiaGroup curGroup = ldapToJahiaGroup (sr); 454 if (curGroup != null) { 455 result.add (curGroup.getGroupKey ()); 456 } 457 } 458 } catch (SizeLimitExceededException slee) { 459 logger.debug ("Search generated more than configured maximum search limit in " + 461 DEFAULT_CONFIGURATION_FILE + 462 ", limiting to " + 463 this.ldapProperties.getProperty (SEARCH_COUNT_LIMIT_PROP) + 464 " first results..."); 465 } catch (NamingException ne) { 466 logger.warn ("JNDI warning",ne); 467 invalidatePublicCtx (); 468 result = new Vector (); 469 } 470 471 return result; 472 473 } 474 475 public JahiaDOMObject getUserGroupAccessAsDOM (int parm1) 476 throws org.jahia.exceptions.JahiaException { 477 478 throw new java.lang.UnsupportedOperationException ( 479 "Method getUserGroupAccessAsDOM() not yet implemented."); 480 } 481 482 494 public JahiaGroup lookupGroup (String groupKey) { 495 497 499 JahiaGroup group = (JahiaGroup) mProvidersGroupCache.get ("k"+groupKey); 500 if (group == null) { 501 JahiaGroupWrapper jgw = (JahiaGroupWrapper) mGroupCache.get ("k"+groupKey); 503 if (jgw == null) { 504 group = lookupGroupInLDAP (removeKeyPrefix(groupKey)); 506 507 if (group != null) { 508 510 mProvidersGroupCache.put ("k"+groupKey, group); 511 mProvidersGroupCache.put ("n"+group.getSiteID()+"_"+group.getGroupname (), group); 513 mGroupCache.put("n"+group.getSiteID()+"_"+group.getGroupname (), new JahiaGroupWrapper(group)); 515 } 516 mGroupCache.put("k"+groupKey, new JahiaGroupWrapper(group)); 518 } else { 519 group = jgw.getGroup(); 520 } 521 } 522 return group; 523 } 524 525 public JahiaGroup getAdministratorGroup (int siteID) { 526 if (ADMINISTRATORS_GROUPNAME != null) 527 return lookupGroup (siteID, ADMINISTRATORS_GROUPNAME); 528 else 529 return null; 530 531 } 532 533 539 540 public Vector getGroupnameList () { 541 return getGroupList (); 542 } 543 544 545 552 public JahiaDOMObject getAppGroupAccessAsDOM (int parm1) 553 throws JahiaException { 554 555 throw new java.lang.UnsupportedOperationException ( 556 "Method getAppGroupAccessAsDOM() not yet implemented."); 557 } 558 559 560 569 570 public Vector getGroupList (int siteID) { 571 return getGroupList (); 572 } 573 574 public JahiaDOMObject getGroupsAsDOM (int parm1) 575 throws org.jahia.exceptions.JahiaException { 576 577 throw new java.lang.UnsupportedOperationException ( 578 "Method getGroupsAsDOM() not yet implemented."); 579 } 580 581 public JahiaDOMObject getGroupPropsAsDOM (int parm1) 582 throws org.jahia.exceptions.JahiaException { 583 584 throw new java.lang.UnsupportedOperationException ( 585 "Method getGroupPropsAsDOM() not yet implemented."); 586 } 587 588 593 594 public JahiaGroup getUsersGroup (int siteID) { 595 if (USERS_GROUPNAME != null) 596 return lookupGroup (siteID, USERS_GROUPNAME); 597 else 598 return null; 599 600 } 601 602 615 public JahiaGroup lookupGroup (int siteID, String name) { 616 if (!isNameValid (name)) { 618 return null; 619 } 620 621 623 625 JahiaGroup group = (JahiaGroup) mProvidersGroupCache.get ("n"+siteID+"_"+name); 626 if (group == null) { 627 JahiaGroupWrapper jgw = (JahiaGroupWrapper) mGroupCache.get ("n"+siteID+"_"+name); 629 if (jgw == null) { 630 group = lookupGroupInLDAP (siteID, name); 631 if (group != null) { 632 634 mProvidersGroupCache.put ("k"+group.getGroupKey(), group); 635 mProvidersGroupCache.put ("n"+group.getSiteID()+"_"+group.getGroupname (), group); 637 mGroupCache.put("k"+group.getGroupKey (), new JahiaGroupWrapper(group)); 639 } 640 mGroupCache.put("n"+siteID+"_"+name, new JahiaGroupWrapper(group)); 642 } else { 643 group = jgw.getGroup(); 644 } 645 } 646 647 return group; 648 } 649 650 665 public Set searchGroups (int siteID, Properties searchCriterias) { 666 Set result = new HashSet (); 667 668 try { 670 Set groupKeys = searchLDAPGroupsByDBProperties(siteID, 671 searchCriterias); 672 Iterator groupKeyEnum = groupKeys.iterator(); 674 while (groupKeyEnum.hasNext()) { 675 String curGroupKey = (String ) groupKeyEnum.next(); 676 JahiaGroup group = lookupGroup(curGroupKey); 677 result.add(group); 678 } 679 680 } catch (JahiaDatabaseException jde) { 681 logger.error("Error while trying to search for groups by properties", 682 jde); 683 } 684 685 try { 687 NamingEnumeration ldapGroups = getGroups (getPublicContext (false), searchCriterias); 688 while (ldapGroups.hasMore ()) { 689 SearchResult sr = (SearchResult) ldapGroups.next (); 690 JahiaLDAPGroup group = ldapToJahiaGroup (sr); 691 if (group != null) { 692 result.add (group); 693 } 694 } 695 696 } catch (SizeLimitExceededException slee) { 697 logger.debug ("Search generated more than configured maximum search limit in " + 698 DEFAULT_CONFIGURATION_FILE + 699 ", limiting to " + 700 this.ldapProperties.getProperty (SEARCH_COUNT_LIMIT_PROP) + 701 " first results..."); 702 } catch (PartialResultException pre) { 703 logger.warn (pre); 704 } catch (NamingException ne) { 705 logger.warn ("JNDI warning",ne); 706 invalidatePublicCtx (); 707 result = new HashSet (); 708 } 709 return result; 710 } 711 712 721 722 public synchronized JahiaGroup createGroup (int parm1, String parm2, 723 Properties parm3) { 724 725 throw new java.lang.UnsupportedOperationException ( 726 "Method createGroup() not yet implemented."); 727 } 728 729 public void updateCache(JahiaGroup jahiaGroup) { 730 mGroupCache.put("k"+jahiaGroup.getGroupKey(), new JahiaGroupWrapper(jahiaGroup)); 731 mGroupCache.put("n"+jahiaGroup.getSiteID()+"_"+jahiaGroup.getGroupname(), new JahiaGroupWrapper(jahiaGroup)); 732 mProvidersGroupCache.put ("k"+jahiaGroup.getGroupKey(), jahiaGroup); 733 mProvidersGroupCache.put ("n"+jahiaGroup.getSiteID()+"_"+jahiaGroup.getGroupname(), jahiaGroup); 734 } 735 736 private void invalidatePublicCtx () { 737 try { 738 invalidateCtx (getPublicContext(false)); 739 } catch (NamingException ne) { 740 logger.error("Couldn't invalidate public LDAP context", ne); 741 } 742 } 743 744 private void invalidateCtx (DirContext ctx) { 745 if (ctx == null) { 746 logger.debug ("Context passed is null, ignoring it..."); 747 return; 748 } 749 try { 750 ctx.close (); 751 } catch (Exception e) { 752 logger.warn (e); 753 } finally { 754 ctx = null; 755 } 756 } 757 758 767 public DirContext getPublicContext (boolean forceRefresh) throws NamingException { 768 if (forceRefresh || publicCtx == null) { 769 try { 771 publicCtx = connectToPublicDir (); 772 } catch (NamingException ne) { 773 logger.warn ("JNDI warning",ne); 774 publicCtx = null; 775 } 776 if (publicCtx == null) { 777 logger.debug ("reconnect failed, returning null context..."); 778 return null; 780 } 781 } 782 return publicCtx; 783 } 784 785 788 private boolean isContextValid(DirContext ctx) { 789 try { 790 ctx.getEnvironment(); 791 return true; 792 } catch (NamingException ne) { 793 logger.debug ("Reconnection is required... ", ne); 794 } catch (NullPointerException npe) { 795 logger.debug ("Reconnection is required... ", npe); 796 } 797 798 return false; 799 } 800 801 private DirContext connectToPublicDir () 802 throws NamingException { 803 if (((JahiaGroupManagerRoutingService)ServicesRegistry 805 .getInstance() 806 .getJahiaGroupManagerService()) 807 .getServerList(PROVIDER_NAME) != null) { 808 logger.debug("connecting to all public dir for groups"); 809 return connectToAllPublicDir(); 810 } 811 812 logger.debug ("Attempting connection to LDAP repository on " + 814 ldapProperties.getProperty (LDAP_URL_PROP) + "..."); 815 Hashtable publicEnv = new Hashtable (11); 816 publicEnv.put (Context.INITIAL_CONTEXT_FACTORY, 817 ldapProperties.getProperty (CONTEXT_FACTORY_PROP)); 818 publicEnv.put (Context.PROVIDER_URL, 819 ldapProperties.getProperty (LDAP_URL_PROP)); 820 publicEnv.put (Context.SECURITY_AUTHENTICATION, 821 ldapProperties.getProperty (AUTHENTIFICATION_MODE_PROP)); 822 publicEnv.put (Context.SECURITY_PRINCIPAL, 823 ldapProperties.getProperty (PUBLIC_BIND_DN_PROP)); 824 publicEnv.put (Context.REFERRAL, 825 ldapProperties.getProperty (LDAP_REFFERAL_PROP, "ignore")); 826 if (ldapProperties.getProperty (PUBLIC_BIND_PASSWORD_PROP) != null) { 827 logger.debug ("Using authentification mode to connect to public dir..."); 828 publicEnv.put (Context.SECURITY_CREDENTIALS, 829 ldapProperties.getProperty (PUBLIC_BIND_PASSWORD_PROP)); 830 } 831 832 return new InitialDirContext (publicEnv); 834 } 835 836 private DirContext connectToAllPublicDir () 837 throws NamingException { 838 DirContext ctx = null; 839 TreeSet servers = ((JahiaGroupManagerRoutingService)ServicesRegistry 840 .getInstance() 841 .getJahiaGroupManagerService()) 842 .getServerList(PROVIDER_NAME); 843 844 for (Iterator ite = servers.iterator(); ite.hasNext();) { 845 ServerBean sb = (ServerBean) ite.next(); 846 String sbUrl = (String )sb.getPublicConnectionParameters() 847 .get(Context.PROVIDER_URL); 848 849 int tryNumber = 1; 850 while (tryNumber <= sb.getMaxReconnection()) { 851 logger.debug ("Attempting connection " 853 + tryNumber 854 + " to LDAP repository on " 855 + sbUrl 856 + "..."); 857 858 try { 860 ctx = new InitialDirContext (sb.getPublicConnectionParameters()); 861 if (isContextValid(ctx)) 862 return ctx; 863 } catch (NamingSecurityException nse) { 864 return null; 866 } catch (NamingException ne) { 867 logger.error("Erreur while getting public context on " + sbUrl, ne); 869 } 870 tryNumber++; 871 } 872 } 873 874 if (ctx == null) { 875 throw new NamingException("All servers used without success..."); 876 } 877 878 return ctx; 879 } 880 881 893 private NamingEnumeration getGroups (DirContext ctx, Properties filters) 894 throws NamingException { 895 896 if (ctx == null) { 897 throw new NamingException ("Context is null !"); 898 } 899 900 StringBuffer filterString = new StringBuffer ("(|(objectClass="+ 901 ldapProperties.getProperty (JahiaGroupManagerLDAPProvider.GROUP_OBJECTCLASS_ATTRIBUTE, "groupOfNames") + 902 ")(objectClass="+ 903 ldapProperties.getProperty (JahiaGroupManagerLDAPProvider.DYNGROUP_OBJECTCLASS_ATTRIBUTE, "groupOfURLs") + 904 "))"); 905 906 if (filters == null) { 907 filters = new Properties (); 908 } 909 910 mapJahiaPropertiesToLDAP (filters); 912 913 if (filters.size () > 0) { 914 915 filterString.insert(0,"(&"); 916 917 Enumeration filterKeys = filters.keys (); 918 while (filterKeys.hasMoreElements ()) { 919 String filterName = (String ) filterKeys.nextElement (); 920 String filterValue = filters.getProperty (filterName); 921 filterValue = JahiaTools.replacePattern (filterValue, "\\", 924 "\\5c"); 925 filterValue = JahiaTools.replacePattern (filterValue, "(", 926 "\\28"); 927 filterValue = JahiaTools.replacePattern (filterValue, ")", 928 "\\29"); 929 930 if ("*".equals (filterName)) { 931 if (this.searchWildCardAttributeList != null) { 934 if (this.searchWildCardAttributeList.size () > 1) { 935 filterString.append ("(|"); 936 } 937 Enumeration attributeEnum = this. 938 searchWildCardAttributeList.elements (); 939 while (attributeEnum.hasMoreElements ()) { 940 String curAttributeName = (String ) 941 attributeEnum.nextElement (); 942 filterString.append ("("); 943 filterString.append (curAttributeName); 944 filterString.append ("="); 945 filterString.append (filterValue); 946 filterString.append (")"); 947 } 948 if (this.searchWildCardAttributeList.size () > 1) { 949 filterString.append (")"); 950 } 951 } 952 } else { 953 filterString.append ("("); 954 filterString.append (filterName); 955 filterString.append ("="); 956 filterString.append (filterValue); 957 filterString.append (")"); 958 } 959 } 960 961 filterString.append (")"); 962 } 963 964 SearchControls searchCtl = new SearchControls (); 965 searchCtl.setSearchScope (SearchControls.SUBTREE_SCOPE); 966 int countLimit = Integer.parseInt (ldapProperties.getProperty (SEARCH_COUNT_LIMIT_PROP)); 967 searchCtl.setCountLimit (countLimit); 968 return getGroups(ctx, searchCtl, filterString); 969 } 970 971 private NamingEnumeration getGroups(DirContext ctx, SearchControls searchCtl, StringBuffer filterString) throws NamingException { 972 logger.debug ("Using filter string [" + filterString.toString () + "]..."); 974 try { 975 return ctx.search ( 976 ldapProperties.getProperty (SEARCH_NAME_PROP), 977 filterString.toString (), 978 searchCtl); 979 } catch (NoInitialContextException nice) { 980 logger.warn("Reconnection required", nice); 981 return getGroups(getPublicContext(true), searchCtl, filterString); 982 } catch (CannotProceedException cpe) { 983 logger.warn("Reconnection required", cpe); 984 return getGroups(getPublicContext(true), searchCtl, filterString); 985 } catch (ServiceUnavailableException sue) { 986 logger.warn("Reconnection required", sue); 987 return getGroups(getPublicContext(true), searchCtl, filterString); 988 } catch (TimeLimitExceededException tlee) { 989 logger.warn("Reconnection required", tlee); 990 return getGroups(getPublicContext(true), searchCtl, filterString); 991 } catch (CommunicationException ce) { 992 logger.warn("Reconnection required", ce); 993 return getGroups(getPublicContext(true), searchCtl, filterString); 994 } 995 } 996 997 1009 private JahiaLDAPGroup ldapToJahiaGroup (SearchResult sr) { 1010 JahiaLDAPGroup group; 1011 Properties groupProps = new Properties (); 1012 String usingGroupKey = null; 1013 Attributes attrs = sr.getAttributes (); 1014 1015 Enumeration attrsEnum = attrs.getAll (); 1016 while (attrsEnum.hasMoreElements ()) { 1017 Attribute curAttr = (Attribute) attrsEnum.nextElement (); 1018 String attrName = curAttr.getID (); 1019 StringBuffer attrValueBuf = new StringBuffer (); 1020 try { 1021 Enumeration curAttrValueEnum = curAttr.getAll (); 1022 while (curAttrValueEnum.hasMoreElements ()) { 1023 Object curAttrValueObj = curAttrValueEnum.nextElement (); 1024 if ((curAttrValueObj instanceof String )) { 1025 attrValueBuf.append ((String ) curAttrValueObj); 1026 } else { 1027 logger.debug ("Converting attribute <" + attrName + "> from class " + 1028 curAttrValueObj.getClass ().toString () + " to String..."); 1029 1030 attrValueBuf.append (curAttrValueObj); 1031 } 1032 attrValueBuf.append ('\n'); 1033 } 1034 } catch (NamingException ne) { 1035 logger.warn ("JNDI warning",ne); 1036 attrValueBuf = new StringBuffer (); 1037 } 1038 String attrValue = attrValueBuf.toString (); 1039 if (attrValue.endsWith ("\n")) { 1040 attrValue = attrValue.substring (0, attrValue.length () - 1); 1041 } 1042 if ((attrName != null) && (attrValue != null)) { 1043 if (usingGroupKey == null) { 1044 if (attrName.equals (ldapProperties.getProperty ( 1045 SEARCH_ATTRIBUTE_PROP))) { 1046 usingGroupKey = attrValue; 1047 } 1048 } 1049 groupProps.setProperty (attrName, attrValue); 1050 if (attrName.equalsIgnoreCase("objectClass")) { 1052 groupProps.setProperty ("objectClass", attrValue); 1053 } 1054 } 1055 } 1056 1057 if (usingGroupKey != null) { 1058 mapLDAPToJahiaProperties (groupProps); 1059 mapDBToJahiaProperties (groupProps, usingGroupKey); 1061 boolean dynamic = groupProps.getProperty("objectClass").indexOf(ldapProperties.getProperty (JahiaGroupManagerLDAPProvider.DYNGROUP_OBJECTCLASS_ATTRIBUTE, "groupOfURLs")) != -1; 1062 try { 1063 if (ldapProperties.getProperty(PRELOAD_GROUP_MEMBERS, "true").equalsIgnoreCase("true")) { 1064 Hashtable members = null; 1065 try { 1066 members = getGroupMembers (sr, dynamic); 1067 } catch (NamingException ne) { 1068 logger.warn ("JNDI warning",ne); 1069 } 1070 1071 group = new JahiaLDAPGroup (0, usingGroupKey, usingGroupKey, 0, 1072 members, 1073 groupProps, dynamic, true); 1074 } else { 1075 group = new JahiaLDAPGroup (0, usingGroupKey, usingGroupKey, 0, 1076 new Hashtable(), 1077 groupProps, dynamic, false); 1078 } 1079 return group; 1080 } catch (JahiaException e) { 1081 logger.warn (e); 1082 return null; 1083 } 1084 } else { 1085 logger.debug ("Ignoring entry " + sr.getName () + 1086 " because it has no valid " + 1087 ldapProperties.getProperty (SEARCH_ATTRIBUTE_PROP) + 1088 " attribute to be mapped onto user key..."); 1089 return null; 1090 } 1091 } 1092 1093 1107 private void mapLDAPToJahiaProperties (Properties groupProps) { 1108 for (Iterator iterator = ldapProperties.keySet().iterator(); iterator.hasNext();) { 1111 String key = (String ) iterator.next(); 1112 if (key.endsWith(".attribute.map")) { 1113 String jahiaProperty = key.substring(12,key.length()-14); 1114 String curProperty = ldapProperties.getProperty(key); 1115 if (groupProps.getProperty (curProperty) != null) { 1116 groupProps.setProperty (jahiaProperty, groupProps.getProperty (curProperty)); 1117 } 1118 } 1119 } 1120 } 1121 1122 1128 private void mapDBToJahiaProperties (Properties groupProps, 1129 String usingGroupKey) { 1130 try { 1131 1133 Properties dbProperties = JahiaGroupDBUtils.getInstance ().getGroupProperties ( 1134 -1, PROVIDER_NAME, usingGroupKey); 1135 groupProps.putAll (dbProperties); 1136 } catch (JahiaException je) { 1137 logger.debug ("SQL Exception occured : Could not read the group [" + 1138 usingGroupKey + "] from the database for site LDAP group"); 1139 } 1142 1143 } 1144 1145 1152 private void mapJahiaPropertiesToLDAP (Properties groupProps) { 1153 for (Iterator iterator = ldapProperties.keySet().iterator(); iterator.hasNext();) { 1154 String key = (String ) iterator.next(); 1155 if (key.endsWith(".attribute.map")) { 1156 String jahiaProperty = key.substring(12,key.length()-14); 1157 String curProperty = ldapProperties.getProperty(key); 1158 if (groupProps.getProperty (jahiaProperty) != null) { 1159 groupProps.put(curProperty, groupProps.remove(jahiaProperty)); 1160 } 1161 } 1162 } 1163 if (groupProps.containsKey("members")) { 1164 groupProps.put(ldapProperties.get(GROUP_MEMBERS_ATTRIBUTE), groupProps.remove("members")); 1165 } 1166 } 1167 1168 private String removeKeyPrefix (String groupKey) { 1169 if (groupKey.startsWith ("{ldap}")) { 1170 return groupKey.substring (6); 1171 } else { 1172 return groupKey; 1173 } 1174 } 1175 1176 private JahiaLDAPGroup lookupGroupInLDAP (String groupKey) { 1177 JahiaLDAPGroup group = null; 1178 Enumeration enumeration = nonExistentGroups.elements (); 1179 1180 logger.debug("lookupGroupInLDAP :: " + groupKey); 1181 1182 while (enumeration.hasMoreElements ()) { 1184 if (groupKey.indexOf (enumeration.nextElement () + ":") != -1) 1185 return group; 1186 } 1187 try { 1189 SearchResult sr = getPublicGroup (getPublicContext (false), groupKey); 1190 if (sr == null) { 1191 return null; 1192 } 1193 group = ldapToJahiaGroup (sr); 1194 1195 } catch (SizeLimitExceededException slee) { 1196 logger.warn ("Search generated more than configured maximum search limit in " + 1197 DEFAULT_CONFIGURATION_FILE + 1198 ", limiting to " + 1199 this.ldapProperties.getProperty (SEARCH_COUNT_LIMIT_PROP) + 1200 " first results..."); 1201 group = null; 1202 1203 } catch (PartialResultException pre) { 1204 logger.warn (pre); 1205 } catch (NamingException ne) { 1206 logger.warn ("JNDI warning",ne); 1207 invalidatePublicCtx (); 1208 group = null; 1209 } 1210 return group; 1211 } 1212 1213 1224 private SearchResult getPublicGroup (DirContext ctx, String cn) 1225 throws NamingException { 1226 1227 Properties filters = new Properties (); 1228 1229 filters.setProperty (ldapProperties.getProperty (SEARCH_ATTRIBUTE_PROP), 1230 cn); 1231 NamingEnumeration answer = getGroups (ctx, filters); 1232 SearchResult sr = null; 1233 if (answer.hasMore ()) { 1234 sr = (SearchResult) answer.next (); 1237 1238 boolean hasMore = false; 1239 try { 1240 hasMore = answer.hasMore (); 1241 } catch (PartialResultException pre) { 1242 logger.warn (pre); 1243 } 1244 1245 if (hasMore) { 1246 logger.info ("Warning : multiple groups with same CN in LDAP repository."); 1250 } 1251 } 1252 return sr; 1253 } 1254 1255 private boolean isNameValid (String name) { 1256 1257 if (name == null) { 1258 return false; 1259 } 1260 1261 if (name.length () == 0) { 1262 return false; 1263 } 1264 1265 String authorizedCharacters = 1266 " -abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789{}"; 1267 1270 1271 boolean badCharFound = false; 1272 for (int i = 0; i < name.length() && !badCharFound; i++) { 1273 badCharFound = authorizedCharacters.indexOf((int)name.charAt(i)) < 0; 1274 if (badCharFound) { 1275 logger.debug ("Bad character found in ldap group name [" + 1276 name + 1277 "] at position " + i); 1278 } 1279 } 1280 1281 return (!badCharFound); 1282 } 1283 1284 private JahiaLDAPGroup lookupGroupInLDAP (int siteID, String name) { 1285 JahiaLDAPGroup group = lookupGroupInLDAP (name); 1286 if (group == null) { 1287 return null; 1288 } 1289 group.setSiteID (siteID); 1290 return group; 1291 } 1292 1293 public void init (SettingsBean jSettings) 1294 throws JahiaInitializationException { 1295 String configPath = jSettings.getJahiaLdapDiskPath (); 1296 String configFileName; 1297 1298 File configFile = new File (configPath + File.separator + 1299 DEFAULT_CONFIGURATION_FILE); 1300 if (configFile.exists ()) { 1301 1302 configFileName = configPath + File.separator + 1303 DEFAULT_CONFIGURATION_FILE; 1304 1305 try { 1306 File ldapPropFile = new File (configFileName); 1307 FileInputStream ldapPropInputStr = new FileInputStream ( 1308 ldapPropFile); 1309 ldapProperties = new Properties (); 1310 ldapProperties.load (ldapPropInputStr); 1311 ldapPropInputStr.close (); 1312 } catch (FileNotFoundException fnfe) { 1313 logger.error ("Error while loading group manager LDAP configuration file", 1314 fnfe); 1315 } catch (IOException ioe) { 1316 logger.error ("Error while loading group manager LDAP configuration file", ioe); 1317 } 1318 1319 } else { 1320 logger.debug ("Config file not found in " + configPath + 1321 File.separator + DEFAULT_CONFIGURATION_FILE); 1322 } 1323 1324 try { 1325 getPublicContext (true); 1326 } catch (NamingException ne) { 1327 logger.error ( 1328 "Error while initializing public browsing connection to LDAP repository", 1329 ne); 1330 invalidatePublicCtx (); 1331 } 1332 1333 String wildCardAttributeStr = ldapProperties.getProperty (JahiaGroupManagerLDAPProvider. 1334 SEARCH_WILDCARD_ATTRIBUTE_LIST); 1335 if (wildCardAttributeStr != null) { 1336 this.searchWildCardAttributeList = new Vector (); 1337 StringTokenizer wildCardTokens = new StringTokenizer ( 1338 wildCardAttributeStr, ", "); 1339 while (wildCardTokens.hasMoreTokens ()) { 1340 String curAttrName = wildCardTokens.nextToken ().trim (); 1341 this.searchWildCardAttributeList.add (curAttrName); 1342 } 1343 } 1344 1345 logger.debug ("Initialized and connected to public repository"); 1346 } 1347 1348 1354 private Hashtable getGroupMembers (SearchResult sr, boolean dynamic) 1355 throws NamingException { 1356 Hashtable members = new Hashtable (); 1357 Attributes attr = sr.getAttributes (); 1358 NamingEnumeration answer = null; 1359 try { 1360 if (dynamic) { 1361 answer = attr.get (ldapProperties.getProperty ( 1362 DYNGROUP_MEMBERS_ATTRIBUTE, "memberurl")). 1363 getAll (); 1364 } else { 1365 answer = attr.get (ldapProperties.getProperty ( 1366 GROUP_MEMBERS_ATTRIBUTE)). 1367 getAll (); 1368 } 1369 } catch (NullPointerException ne) { 1370 logger.debug ("No members"); 1371 } 1372 1373 1379 String searchProperties = ldapProperties.getProperty (SEARCH_USER_ATTRIBUTE_NAME); 1381 boolean searchUserDefined = (!(searchProperties == null) && (searchProperties.length() > 0)); 1382 1383 logger.debug ("Getting members for group, dynamic="+dynamic+", searchUserDefined="+searchUserDefined); 1384 1385 if (answer != null) { 1386 while (answer.hasMore ()) { 1387 String userKey = (String )answer.next (); 1388 if (dynamic) { 1389 Properties p = new Properties(); 1390 p.put("ldap.url", userKey); 1391 Set t = getUserManagerProvider().searchUsers(0,p); 1392 for (Iterator iterator = t.iterator(); iterator.hasNext();) { 1393 JahiaUser jahiaUser = (JahiaUser) iterator.next(); 1394 members.put(jahiaUser.getName(), jahiaUser); 1395 } 1396 } else { 1397 JahiaUser user = null; 1398 if (searchUserDefined) { user = getUserManagerProvider(). 1400 lookupUser (userKey, 1401 ldapProperties 1402 .getProperty ( 1403 SEARCH_USER_ATTRIBUTE_NAME)); 1404 } else { user = getUserManagerProvider() 1406 .lookupUserFromDN( 1407 userKey); 1408 } 1409 if (user != null) 1410 members.put (user.getName(), user); 1411 } 1412 } 1413 } 1414 return members; 1415 } 1416 1417 1418 public synchronized JahiaUserManagerLDAPProvider getUserManagerProvider() { 1419 if (userProvider == null) { 1420 Vector v = ServicesRegistry.getInstance().getJahiaUserManagerService().getProviderList(); 1421 for (Iterator iterator = v.iterator(); iterator.hasNext();) { 1422 UserManagerProviderBean userManagerProviderBean = (UserManagerProviderBean) iterator.next(); 1423 if (userManagerProviderBean.getClassName().equals(JahiaUserManagerLDAPProvider.class.getName())) { 1424 JahiaUserManagerLDAPProvider jahiaUserManagerLDAPProvider = (JahiaUserManagerLDAPProvider)userManagerProviderBean.getInstance(); 1425 if (jahiaUserManagerLDAPProvider.getUrl().equals(ldapProperties.get(LDAP_URL_PROP))) { 1426 userProvider = jahiaUserManagerLDAPProvider; 1427 } 1428 } 1429 } 1430 } 1431 return userProvider; 1432 } 1433 1434 1443 private String makeLIKEString (String input) { 1444 String result = JahiaTools.replacePattern(input, "*", "%"); 1445 result = JahiaTools.replacePattern(result, "'", "\\'"); 1446 result = JahiaTools.replacePattern(result, "\"", "\\\""); 1447 result = JahiaTools.replacePattern(result, "_", "\\_"); 1448 return result; 1449 } 1450 1451 private synchronized Set searchLDAPGroupsByDBProperties (int siteID, 1452 Properties searchCriterias) 1453 throws JahiaDatabaseException { 1454 Set groupKeys = new HashSet(); 1455 1456 Connection dbConn = org.jahia.services.database.ConnectionDispenser. 1458 getConnection(); 1459 if (dbConn == null) { 1460 return groupKeys; 1461 } 1462 1463 if (searchCriterias == null) { 1464 searchCriterias = new Properties(); 1465 searchCriterias.setProperty("*", "*"); 1466 } 1467 1468 boolean haveWildCardProperty = false; 1469 if (searchCriterias.getProperty("*") != null) { 1470 haveWildCardProperty = true; 1471 } 1472 1473 Statement statement = null; 1475 try { 1476 statement = dbConn.createStatement(); 1477 if (statement != null) { 1478 1479 StringBuffer query; 1480 1481 query = 1482 new StringBuffer ( 1483 "SELECT DISTINCT grpkey_jahia_grp_prop FROM jahia_grp_prop WHERE provider_jahia_grp_prop='"); 1484 query.append(PROVIDER_NAME); 1485 query.append("' AND "); 1486 Enumeration criteriaNames = searchCriterias.keys(); 1487 while (criteriaNames.hasMoreElements()) { 1488 String curCriteriaName = (String ) criteriaNames. 1489 nextElement(); 1490 String curCriteriaValue = makeLIKEString( 1491 searchCriterias.getProperty(curCriteriaName)); 1492 if ("*".equals(curCriteriaName)) { 1493 query.append( 1495 " value_jahia_grp_prop LIKE '"); 1496 query.append(curCriteriaValue); 1497 query.append("' "); 1498 if (criteriaNames.hasMoreElements()) { 1499 query.append(" AND "); 1500 } 1501 } else { 1502 query.append( 1503 "(name_jahia_grp_prop='"); 1504 query.append(makeLIKEString(curCriteriaName)); 1505 query.append( 1506 "' AND value_jahia_grp_prop LIKE '"); 1507 query.append(curCriteriaValue); 1508 query.append("') "); 1509 if (criteriaNames.hasMoreElements()) { 1510 query.append(" AND "); 1511 } 1512 } 1513 } 1514 logger.debug("Executing query [" + query.toString() + "]"); 1515 1516 ResultSet rs = statement.executeQuery(query.toString()); 1517 if (rs != null) { 1518 while (rs.next()) { 1519 String name = rs.getString(1); 1520 if (name != null) { 1521 groupKeys.add(name); 1522 } 1523 } 1524 } 1525 } 1526 } catch (SQLException ex) { 1527 logger.error("Error while searching groups in site " + siteID, ex); 1528 } finally { 1529 closeStatement(statement); 1530 } 1531 1532 return groupKeys; 1533 1534 } 1535 1536 private void closeStatement (Statement statement) 1538 throws JahiaDatabaseException { 1539 try { 1541 if (statement != null) { 1542 statement.close(); 1543 } 1544 } catch (SQLException sqlEx) { 1545 throw new JahiaDatabaseException( 1546 "Could not close a statement in JahiaDBUser", 1547 sqlEx, JahiaDatabaseException.ERROR_SEVERITY); 1548 } 1549 } 1550 1551} 1552 | Popular Tags |