1 40 41 42 package org.jahia.services.usermanager; 43 44 import java.io.File ; 45 import java.io.FileInputStream ; 46 import java.io.FileNotFoundException ; 47 import java.io.IOException ; 48 import java.sql.Connection ; 49 import java.sql.ResultSet ; 50 import java.sql.SQLException ; 51 import java.sql.Statement ; 52 import java.util.*; 53 import javax.naming.*; 54 import javax.naming.directory.Attribute ; 55 import javax.naming.directory.Attributes ; 56 import javax.naming.directory.DirContext ; 57 import javax.naming.directory.InitialDirContext ; 58 import javax.naming.directory.SearchControls ; 59 import javax.naming.directory.SearchResult ; 60 61 import org.jahia.data.JahiaDBDOMObject; 62 import org.jahia.data.JahiaDOMObject; 63 import org.jahia.exceptions.JahiaException; 64 import org.jahia.exceptions.JahiaInitializationException; 65 import org.jahia.exceptions.database.JahiaDatabaseException; 66 import org.jahia.registries.ServicesRegistry; 67 import org.jahia.services.acl.JahiaACLManagerService; 68 import org.jahia.services.cache.Cache; 69 import org.jahia.services.cache.CacheFactory; 70 import org.jahia.services.database.JahiaIncrementorsDBService; 71 import org.jahia.settings.SettingsBean; 72 import org.jahia.utils.JahiaTools; 73 74 85 public class JahiaUserManagerLDAPProvider extends JahiaUserManagerProvider { 86 87 88 private static org.apache.log4j.Logger logger = 89 org.apache.log4j.Logger.getLogger(JahiaUserManagerLDAPProvider.class); 90 91 private static final String USERNAME_PROPERTY_NAME = "username"; 92 93 private static String DEFAULT_CONFIGURATION_FILE = "users.ldap.properties"; 94 95 private static String CONTEXT_FACTORY_PROP = "users.ldap.context.factory"; 96 private static String LDAP_URL_PROP = "users.ldap.url"; 97 private static String AUTHENTIFICATION_MODE_PROP = 98 "users.ldap.authentification.mode"; 99 private static String PUBLIC_BIND_DN_PROP = "users.ldap.public.bind.dn"; 100 private static String PUBLIC_BIND_PASSWORD_PROP = 101 "users.ldap.public.bind.password"; 102 103 private static String UID_SEARCH_ATTRIBUTE_PROP = 104 "users.ldap.uid.search.attribute"; 105 private static String UID_SEARCH_NAME_PROP = "users.ldap.uid.search.name"; 106 private static String USERS_OBJECTCLASS_ATTRIBUTE = 107 "users.ldap.search.objectclass"; 108 109 private static String LDAP_REFFERAL_PROP = "users.ldap.refferal"; 110 private static String SEARCH_COUNT_LIMIT_PROP = 111 "users.ldap.search.countlimit"; 112 private static String SEARCH_WILDCARD_ATTRIBUTE_LIST = 113 "users.ldap.search.wildcards.attributes"; 114 115 private static String LDAP_USERNAME_ATTRIBUTE = 116 "users.ldap.username.attribute.map"; 117 118 private Properties ldapProperties = null; 119 120 private DirContext publicCtx = null; 121 private boolean connectedToPublic = false; 122 private Vector searchWildCardAttributeList = null; 123 124 public static final String PROVIDER_NAME = "ldap"; 125 126 private final String MSG_INTERNAL_ERROR = new String ( 127 "JahiaUserManagerLDAPProvider"); 128 129 private static JahiaUserManagerLDAPProvider instance; 130 131 public static final String LDAP_USER_CACHE = "LDAPUsersCache"; 133 134 135 public static final String PROVIDERS_USER_CACHE = "ProvidersUsersCache"; 136 137 private Cache mUserCache; 138 private Cache mProvidersUserCache; 139 140 private JahiaGroupManagerRoutingService mGroupService = null; 142 private JahiaACLManagerService mACLService = null; 143 private JahiaIncrementorsDBService mIncrementorService = null; 144 145 146 public static final int ROOT_USER_ID = 0; 147 148 149 public static final int GUEST_USER_ID = 1; 150 151 158 protected JahiaUserManagerLDAPProvider () 159 throws JahiaException { 160 mUserCache = CacheFactory.createCache(LDAP_USER_CACHE); 161 mProvidersUserCache = CacheFactory.createCache(PROVIDERS_USER_CACHE); 162 163 ServicesRegistry registry = ServicesRegistry.getInstance(); 164 if (registry != null) { 165 mIncrementorService = registry.getJahiaIncrementorsDBService(); 166 if (mIncrementorService == null) { 167 throw new JahiaException(MSG_INTERNAL_ERROR, 168 "User manager could not get the Incrementors DB Service instance.", 169 JahiaException.SERVICE_ERROR, 170 JahiaException.CRITICAL_SEVERITY); 171 } 172 173 mGroupService = 174 (JahiaGroupManagerRoutingService) registry. 175 getJahiaGroupManagerService(); 176 if (mGroupService == null) { 178 throw new JahiaException(MSG_INTERNAL_ERROR, 179 "User manager could not get the Group Manager Service instance.", 180 JahiaException.SERVICE_ERROR, 181 JahiaException.CRITICAL_SEVERITY); 182 } 183 184 mACLService = registry.getJahiaACLManagerService(); 185 if (mACLService == null) { 186 throw new JahiaException(MSG_INTERNAL_ERROR, 187 "User manager could not get the ACL Manager Service instance.", 188 JahiaException.SERVICE_ERROR, 189 JahiaException.CRITICAL_SEVERITY); 190 } 191 } else { 192 throw new JahiaException(MSG_INTERNAL_ERROR, 193 "User manager could not get the Service Registry instance.", 194 JahiaException.REGISTRY_ERROR, 195 JahiaException.CRITICAL_SEVERITY); 196 } 197 } 198 199 205 public static JahiaUserManagerLDAPProvider getInstance () { 206 if (instance == null) { 207 try { 208 instance = new JahiaUserManagerLDAPProvider(); 209 } catch (JahiaException ex) { 210 logger.error( 211 "Could not create an instance of the JahiaUserManagerLDAPProvider class"); 212 } 213 } 214 return instance; 215 } 216 217 231 public synchronized JahiaUser createUser (String name, 232 String password, 233 String userKey, 234 int siteID, 235 Properties properties) { 236 if (!isNameValid(name)) { 237 return null; 238 } 239 240 if (!isNameValid(password)) { 242 return null; 243 } 244 245 if (userExists(siteID, name)) { 247 return null; 248 } 249 250 JahiaGroup usersGroup = mGroupService.getUsersGroup(siteID); 252 JahiaGroup guestGroup = mGroupService.getGuestGroup(siteID); 253 if ( (usersGroup == null) || (guestGroup == null)) { 254 logger.debug( 255 "createUser() : could not get the [users] or/and [guest] group instance."); 256 return null; 257 } 258 259 int userID; 261 try { 262 userID = mIncrementorService.autoIncrement("jahia_users"); 263 logger.debug("got new user ID = [" + Integer.toString(userID) + "]"); 264 } catch (JahiaException ex) { 265 logger.warn( 266 "Exception !!! Could not get a new user ID from the incrementor DB"); 267 return null; 268 } 269 270 password = encryptPassword(password); 272 if (password == null) { 273 logger.debug("createUser() could not encrypt the user password."); 274 return null; 275 } 276 277 JahiaLDAPUser user = null; 279 user = new JahiaLDAPUser(userID, name, password, userKey, siteID, 280 new UserProperties(properties, true), null); 281 282 if (user == null) { 283 logger.debug( 284 "createUser() couldn't create and instance of JahiaUser class"); 285 return null; 286 } 287 288 if (addUserIntoLDAP (userID, name, password, userKey, siteID, properties)) { 290 mUserCache.put ("k"+user.getUserKey(), new JahiaUserWrapper(user)); 291 292 logger.debug ("User [" + name + "] was added into the database and in the cache"); 293 294 296 mProvidersUserCache.put("k"+user.getUserKey(), user); 297 298 mUserCache.put("n"+user.getSiteID()+"_"+user.getUsername(), new JahiaUserWrapper(user)); 299 mProvidersUserCache.put("n"+user.getSiteID()+"_"+user.getUsername(), user); 300 301 usersGroup.addMember (user); 303 guestGroup.addMember (user); 304 } else { 305 logger.debug ("Could not add the user [" + name + "] in the database!!"); 306 user = null; 307 } 308 309 return user; 310 } 311 312 323 public synchronized boolean deleteUser (JahiaUser user) { 324 return false; 325 326 } 327 328 337 public JahiaUser lookupUser (String userKey) { 338 339 341 JahiaUser user = (JahiaUser)mProvidersUserCache.get ("k"+userKey); 342 343 if (user == null) { 345 JahiaUserWrapper juw = (JahiaUserWrapper) mUserCache.get ("k"+userKey); 347 348 if (juw == null) { 349 user = lookupUserInLDAP (removeKeyPrefix(userKey)); 351 352 if (user != null) { 353 355 mProvidersUserCache.put("k"+userKey, user); 356 357 mUserCache.put("n"+user.getSiteID()+"_"+user.getUsername(), new JahiaUserWrapper(user)); 359 mProvidersUserCache.put("n"+user.getSiteID()+"_"+user.getUsername(), user); 360 } 361 mUserCache.put ("k"+userKey, new JahiaUserWrapper(user)); 363 } else { 364 user = juw.getUser(); 365 } 366 } 367 368 return user; 369 } 370 371 372 382 public JahiaUser lookupUser (int siteID, String name) { 383 404 432 JahiaUser user = lookupUser ("{ldap}"+name); 434 if (user != null) 435 user.setSiteID(-1); 437 return user; 438 } 440 441 450 public JahiaUser lookupUser (String userKey, String searchAttributeName) { 451 452 454 JahiaUser user = (JahiaUser)mProvidersUserCache.get ("k"+userKey); 455 456 if (user == null) { 458 JahiaUserWrapper juw = (JahiaUserWrapper) mUserCache.get ("k"+userKey); 460 461 if (juw == null) { 462 user = lookupUserInLDAP (removeKeyPrefix(userKey), searchAttributeName); 464 465 if (user != null) { 466 468 mProvidersUserCache.put("k"+userKey, user); 469 470 mUserCache.put("n"+user.getSiteID()+"_"+user.getUsername(), new JahiaUserWrapper(user)); 472 mProvidersUserCache.put("n"+user.getSiteID()+"_"+user.getUsername(), user); 473 } 474 mUserCache.put ("k"+userKey, new JahiaUserWrapper(user)); 476 } else { 477 user = juw.getUser(); 478 } 479 } 480 return user; 481 } 482 483 494 public boolean userExists (int siteID, String name) { 495 if (name == null) { 497 return false; 498 } 499 500 if (name.length() == 0) { 502 return false; 503 } 504 505 return (lookupUser(siteID, name) != null); 506 } 507 508 516 public Vector getUsernameList (int siteID) { 517 518 Vector result = new Vector(); 519 520 try { 521 522 NamingEnumeration answer = getUsers(getPublicContext(false), new Properties(), ldapProperties.getProperty (UID_SEARCH_NAME_PROP), SearchControls.SUBTREE_SCOPE); 523 while (answer.hasMore()) { 524 SearchResult sr = (SearchResult ) answer.next(); 525 JahiaUser curUser = ldapToJahiaUser(sr); 526 if (curUser != null) { 527 result.add (curUser.getUsername ()); 528 } 529 } 530 } catch (SizeLimitExceededException slee) { 531 logger.debug ("Search generated more than configured maximum search limit in " + 533 DEFAULT_CONFIGURATION_FILE + 534 ", limiting to " + 535 this.ldapProperties.getProperty (SEARCH_COUNT_LIMIT_PROP) + 536 " first results..."); 537 } catch (NamingException ne) { 538 logger.warn ("JNDI warning",ne); 539 invalidatePublicCtx (); 540 result = new Vector (); 541 } 542 543 return result; 544 } 545 546 554 public Vector getUserList (int siteID) { 555 556 return getUserList (); 557 558 } 559 560 561 566 public Vector getUserList () { 567 568 Vector result = new Vector (); 569 570 try { 571 572 NamingEnumeration answer = getUsers(getPublicContext(false), new Properties(), ldapProperties.getProperty (UID_SEARCH_NAME_PROP), SearchControls.SUBTREE_SCOPE); 573 while (answer.hasMore()) { 574 SearchResult sr = (SearchResult ) answer.next(); 575 JahiaUser curUser = ldapToJahiaUser(sr); 576 if (curUser != null) { 577 result.add(curUser.getUserKey()); 578 } 579 } 580 } catch (SizeLimitExceededException slee) { 581 logger.debug( 583 "Search generated more than configured maximum search limit in " + 584 DEFAULT_CONFIGURATION_FILE + 585 ", limiting to " + 586 this.ldapProperties.getProperty(SEARCH_COUNT_LIMIT_PROP) + 587 " first results..."); 588 } catch (NamingException ne) { 589 logger.warn ("JNDI warning",ne); 590 invalidatePublicCtx (); 591 result = new Vector (); 592 } 593 594 return result; 595 } 596 597 612 public Set searchUsers (int siteID, Properties searchCriterias) { 613 614 Set result = new HashSet(); 615 try { 617 Set userKeys = searchLDAPUsersByDBProperties(siteID, 618 searchCriterias); 619 Iterator userKeyEnum = userKeys.iterator(); 621 while (userKeyEnum.hasNext()) { 622 String curUserKey = (String ) userKeyEnum.next(); 623 JahiaUser user = lookupUser(curUserKey); 624 result.add(user); 625 } 626 627 } catch (JahiaDatabaseException jde) { 628 logger.error("Error while trying to search for user by properties", 629 jde); 630 } 631 632 try { 634 NamingEnumeration ldapUsers = getUsers(getPublicContext(false), 635 searchCriterias, ldapProperties.getProperty (UID_SEARCH_NAME_PROP), SearchControls.SUBTREE_SCOPE); 636 while (ldapUsers.hasMore()) { 637 SearchResult sr = (SearchResult ) ldapUsers.next(); 638 JahiaLDAPUser user = ldapToJahiaUser(sr); 639 if (user != null) { 640 result.add(user); 641 } 642 } 643 } catch (PartialResultException pre) { 644 logger.warn (pre); 645 } catch (SizeLimitExceededException slee) { 646 logger.debug( 649 "Search generated more than configured maximum search limit in " + 650 DEFAULT_CONFIGURATION_FILE + 651 ", limiting to " + 652 this.ldapProperties.getProperty(SEARCH_COUNT_LIMIT_PROP) + 653 " first results..."); 654 } catch (NamingException ne) { 655 logger.warn ("JNDI warning",ne); 656 invalidatePublicCtx (); 657 result = new HashSet (); 658 } 659 return result; 660 } 661 662 public void init (SettingsBean jSettings) 663 throws JahiaInitializationException { 664 String configPath = jSettings.getJahiaLdapDiskPath(); 665 String configFileName; 666 667 File configFile = new File (configPath + File.separator + 668 DEFAULT_CONFIGURATION_FILE); 669 if (configFile.exists()) { 670 671 configFileName = configPath + File.separator + 672 DEFAULT_CONFIGURATION_FILE; 673 674 try { 675 File ldapPropFile = new File (configFileName); 676 FileInputStream ldapPropInputStr = new FileInputStream ( 677 ldapPropFile); 678 ldapProperties = new Properties(); 679 ldapProperties.load(ldapPropInputStr); 680 ldapPropInputStr.close(); 681 if (!ldapProperties.containsKey(LDAP_USERNAME_ATTRIBUTE)) { 682 ldapProperties.put(LDAP_USERNAME_ATTRIBUTE, ldapProperties.get(UID_SEARCH_ATTRIBUTE_PROP)); 683 } 684 } catch (FileNotFoundException fnfe) { 685 logger.error( 686 "Error while loading user manager LDAP configuration file", 687 fnfe); 688 689 } catch (IOException ioe) { 690 logger.error( 691 "Error while loading user manager LDAP configuration file", 692 ioe); 693 } 694 695 } else { 696 logger.debug( 697 "Config file not found in " + configPath + File.separator + 698 DEFAULT_CONFIGURATION_FILE); 699 } 700 701 try { 702 getPublicContext (true); 703 } catch (NamingException ne) { 704 logger.error( 705 "Error while initializing public browsing connection to LDAP repository", 706 ne); 707 invalidatePublicCtx(); 708 } 709 710 String wildCardAttributeStr = ldapProperties.getProperty( 711 JahiaUserManagerLDAPProvider.SEARCH_WILDCARD_ATTRIBUTE_LIST); 712 if (wildCardAttributeStr != null) { 713 this.searchWildCardAttributeList = new Vector(); 714 StringTokenizer wildCardTokens = new StringTokenizer( 715 wildCardAttributeStr, ", "); 716 while (wildCardTokens.hasMoreTokens()) { 717 String curAttrName = wildCardTokens.nextToken().trim(); 718 this.searchWildCardAttributeList.add(curAttrName); 719 } 720 } 721 722 logger.debug("Initialized and connected to public repository"); 723 } 724 725 733 public synchronized int getNbUsers () 734 throws JahiaException { 735 return -1; 736 } 737 738 749 public int getNbUsers (int siteID) 750 throws JahiaException { 751 return getNbUsers(); 752 } 753 754 761 private Vector getUserIds (int siteID) { 762 Vector result = new Vector(); 763 return result; 764 } 765 766 776 public JahiaDOMObject getUsersAsDOM (int siteID) 777 throws JahiaException { 778 779 JahiaDBDOMObject dom = null; 780 781 return dom; 782 } 783 784 794 public JahiaDOMObject getUserPropsAsDOM (int siteID) 795 throws JahiaException { 796 797 JahiaDBDOMObject dom = null; 798 799 return dom; 800 } 801 802 public void updateCache(JahiaUser jahiaUser) { 803 mUserCache.put("k"+jahiaUser.getName(), new JahiaUserWrapper(jahiaUser)); 804 mProvidersUserCache.put("k"+jahiaUser.getName(), jahiaUser); 805 mUserCache.put("n"+jahiaUser.getSiteID()+"_"+jahiaUser.getUsername(), new JahiaUserWrapper(jahiaUser)); 806 mProvidersUserCache.put("n"+jahiaUser.getSiteID()+"_"+jahiaUser.getUsername(), jahiaUser); 807 } 808 809 private boolean addUserIntoLDAP (int id, String username, String password, 810 String userKey, int siteID, 811 Properties properties) { 812 return true; 813 } 814 815 private String removeKeyPrefix (String userKey) { 816 if (userKey.startsWith("{ldap}")) { 817 return userKey.substring(6); 818 } else { 819 return userKey; 820 } 821 } 822 823 private JahiaLDAPUser lookupUserInLDAP (int siteID, String name) { 824 JahiaLDAPUser user = lookupUserInLDAP(name); 825 if (user == null) { 826 return null; 827 } 828 user.setSiteID(-1); 830 return user; 831 } 832 833 private JahiaLDAPUser lookupUserInLDAP (String userKey) { 834 JahiaLDAPUser user = null; 835 836 try { 837 SearchResult sr = getPublicUser (getPublicContext (false), ldapProperties.getProperty (UID_SEARCH_ATTRIBUTE_PROP), userKey); 838 if (sr == null) { 839 return null; 840 } 841 user = ldapToJahiaUser (sr); 842 } catch (SizeLimitExceededException slee) { 843 logger.debug ("Search generated more than configured maximum search limit in " + 844 DEFAULT_CONFIGURATION_FILE + 845 ", limiting to " + 846 this.ldapProperties.getProperty (SEARCH_COUNT_LIMIT_PROP) + 847 " first results..."); 848 user = null; 849 850 } catch (NamingException ne) { 851 logger.warn ("JNDI warning",ne); 852 invalidatePublicCtx (); 853 user = null; 854 } 855 return user; 856 } 857 867 private JahiaLDAPUser lookupUserInLDAP (String userKey, String searchAttributeName) { 868 JahiaLDAPUser user = null; 869 870 try { 871 SearchResult sr = getPublicUser (getPublicContext (false), searchAttributeName, userKey); 872 if (sr == null) { 873 return null; 874 } 875 user = ldapToJahiaUser (sr); 876 } catch (SizeLimitExceededException slee) { 877 logger.debug ("Search generated more than configured maximum search limit in " + 878 DEFAULT_CONFIGURATION_FILE + 879 ", limiting to " + 880 this.ldapProperties.getProperty (SEARCH_COUNT_LIMIT_PROP) + 881 " first results..."); 882 user = null; 883 884 } catch (NamingException ne) { 885 logger.warn ("JNDI warning",ne); 886 invalidatePublicCtx (); 887 user = null; 888 } 889 return user; 890 } 891 892 public JahiaLDAPUser lookupUserFromDN(String dn) { 893 logger.debug ("Lookup user from dn " + dn); 894 JahiaLDAPUser user = null; 895 if (mUserCache.containsKey("d"+dn)) { 896 return (JahiaLDAPUser) mUserCache.get("d"+dn); 897 } 898 try { 899 Attributes attributes = getUser (getPublicContext(false), dn); 900 user = ldapToJahiaUser (attributes, dn); 901 mUserCache.put("d"+dn, user); 902 mUserCache.put("k"+user.getUserKey(), new JahiaUserWrapper(user)); 903 mUserCache.put("n"+user.getSiteID()+"_"+user.getUsername(), new JahiaUserWrapper(user)); 904 mProvidersUserCache.put("n"+user.getSiteID()+"_"+user.getUsername(), user); 905 } catch (NameNotFoundException nnfe) { 906 user = null; 907 } catch (NamingException ne) { 908 logger.warn ("JNDI warning",ne); 909 invalidatePublicCtx (); 910 user = null; 911 } 912 return user; 913 } 914 915 927 private JahiaLDAPUser ldapToJahiaUser (SearchResult sr) { 928 Attributes attrs = sr.getAttributes(); 929 String dn = sr.getName() + "," + ldapProperties.getProperty (UID_SEARCH_NAME_PROP); 930 return ldapToJahiaUser(attrs, dn); 931 } 932 933 private JahiaLDAPUser ldapToJahiaUser(Attributes attrs, String dn) { 934 JahiaLDAPUser user = null; 935 UserProperties userProps = new UserProperties (); 936 String usingUserKey = null; 937 938 Enumeration attrsEnum = attrs.getAll(); 939 while (attrsEnum.hasMoreElements()) { 940 Attribute curAttr = (Attribute ) attrsEnum.nextElement(); 941 String attrName = curAttr.getID(); 942 StringBuffer attrValueBuf = new StringBuffer (); 943 try { 944 Enumeration curAttrValueEnum = curAttr.getAll(); 945 while (curAttrValueEnum.hasMoreElements()) { 946 Object curAttrValueObj = curAttrValueEnum.nextElement(); 947 if ( (curAttrValueObj instanceof String )) { 948 attrValueBuf.append( (String ) curAttrValueObj); 949 } else { 950 logger.debug("Converting attribute <" + attrName + 951 "> from class " + 952 curAttrValueObj.getClass().toString() + 953 " to String..."); 954 955 attrValueBuf.append(curAttrValueObj); 956 } 957 attrValueBuf.append('\n'); 958 } 959 } catch (NamingException ne) { 960 logger.warn ("JNDI warning",ne); 961 attrValueBuf = new StringBuffer (); 962 } 963 String attrValue = attrValueBuf.toString(); 964 if (attrValue.endsWith("\n")) { 965 attrValue = attrValue.substring(0, attrValue.length() - 1); 966 } 967 if ( (attrName != null) && (attrValue != null)) { 968 if (usingUserKey == null) { 969 if (attrName.equalsIgnoreCase( 970 ldapProperties.getProperty(UID_SEARCH_ATTRIBUTE_PROP))) { 971 usingUserKey = attrValue; 972 } 973 } 974 UserProperty curUserProperty = new UserProperty(attrName, attrValue, true); 976 userProps.setUserProperty(attrName, curUserProperty); 977 } 978 } 979 if (usingUserKey != null) { 980 mapLDAPToJahiaProperties(userProps); 981 mapDBToJahiaProperties (userProps, JahiaLDAPUser.USERKEY_LDAP_PREFIX + usingUserKey); 983 985 String name = usingUserKey; 986 987 if (ldapProperties.getProperty(LDAP_USERNAME_ATTRIBUTE) != null 988 && ldapProperties.getProperty(LDAP_USERNAME_ATTRIBUTE).length() > 0) { 989 name = userProps 990 .getProperty 991 (ldapProperties 992 .getProperty( 993 LDAP_USERNAME_ATTRIBUTE)); 994 } 995 996 user = new JahiaLDAPUser (0, 997 name, 998 "", 999 usingUserKey, 1000 0, 1001 userProps, 1002 dn); 1003 } else { 1004 logger.debug ("Ignoring entry " + dn + 1005 " because it has no valid " + 1006 ldapProperties.getProperty (UID_SEARCH_ATTRIBUTE_PROP) + 1007 " attribute to be mapped onto user key..."); 1008 } 1009 1010 return user; 1011 } 1012 1013 1014 1015 1030 private void mapLDAPToJahiaProperties (UserProperties userProps) { 1031 for (Iterator iterator = ldapProperties.keySet().iterator(); 1034 iterator.hasNext(); ) { 1035 String key = (String ) iterator.next(); 1036 if (key.endsWith(".attribute.map")) { 1037 String jahiaProperty = key.substring(11, key.length() - 14); 1038 String curProperty = ldapProperties.getProperty(key); 1039 if (userProps.getUserProperty(curProperty) != null) { 1040 UserProperty sourceProp = userProps.getUserProperty(curProperty); 1041 UserProperty targetProp = new UserProperty(jahiaProperty, sourceProp.getValue(), sourceProp.isReadOnly()); 1042 userProps.setUserProperty(jahiaProperty, 1043 targetProp); 1044 } else { 1045 UserProperty targetProp = new UserProperty(jahiaProperty, "", true); 1050 userProps.setUserProperty(jahiaProperty, 1051 targetProp); 1052 } 1053 } 1054 } 1055 } 1056 1057 1064 private void mapJahiaPropertiesToLDAP (Properties userProps) { 1065 for (Iterator iterator = ldapProperties.keySet().iterator(); 1066 iterator.hasNext(); ) { 1067 String key = (String ) iterator.next(); 1068 if (key.endsWith(".attribute.map")) { 1069 String jahiaProperty = key.substring(11, key.length() - 14); 1070 String curProperty = ldapProperties.getProperty(key); 1071 if (userProps.getProperty(jahiaProperty) != null) { 1072 userProps.setProperty(curProperty, 1073 (String ) userProps.remove(jahiaProperty)); 1074 } 1075 } 1076 } 1077 } 1078 1079 private boolean isNameValid (String name) { 1081 1082 if (name == null) { 1083 return false; 1084 } 1085 1086 if (name.length() == 0) { 1087 return false; 1088 } 1089 1090 String authorizedCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789{}"; 1091 1094 1095 boolean badCharFound = false; 1096 for (int i = 0; i < name.length() && !badCharFound; i++) { 1097 badCharFound = authorizedCharacters.indexOf((int)name.charAt(i)) < 0; 1098 if (badCharFound) { 1099 logger.debug ("Bad character found in LDAP user name [" + 1100 name + 1101 "] at position " + i); 1102 } 1103 } 1104 1105 1106 return (!badCharFound); 1107 } 1108 1109 1120 public DirContext getPublicContext (boolean forceRefresh) throws NamingException { 1121 if (forceRefresh || publicCtx == null) { 1122 try { 1124 publicCtx = connectToPublicDir (); 1125 } catch (NamingException ne) { 1126 logger.warn ("JNDI warning",ne); 1127 publicCtx = null; 1128 } 1129 if (publicCtx == null) { 1130 logger.debug ("reconnect failed, returning null context..."); 1131 return null; 1133 } 1134 } 1135 return publicCtx; 1136 } 1137 1138 1141 private boolean isContextValid(DirContext ctx) { 1142 try { 1143 ctx.getEnvironment(); 1144 return true; 1145 } catch (NamingException ne) { 1146 logger.warn ("Reconnection is required... ", ne); 1147 } catch (NullPointerException npe) { 1148 logger.warn ("Reconnection is required... ", npe); 1149 } 1150 1151 return false; 1152 } 1153 1154 1163 public synchronized boolean login (String userKey, String userPassword) { 1164 String dn = null; 1165 String userFinalKey = userKey; 1166 1167 if ("".equals (userPassword)) { 1168 logger.debug ("Empty passwords are not authorized for LDAP login ! Failing user " + 1169 userKey + " login request."); 1170 return false; 1171 } 1172 1173 userFinalKey = removeKeyPrefix(userKey); 1174 DirContext privateCtx = null; 1175 1176 try { 1177 dn = ((JahiaLDAPUser) lookupUser (userFinalKey)).getDN(); 1178 1180 privateCtx = connectToPrivateDir (dn, userPassword); 1181 1182 if (privateCtx == null) { 1183 dn = null; 1184 } 1185 1186 invalidateCtx (privateCtx); 1187 1188 } catch (javax.naming.CommunicationException ce) { 1191 logger.warn ("CommunicationException", ce); 1192 logger.debug ("Invalidating connection to public LDAP context..."); 1193 invalidateCtx (privateCtx); 1194 dn = null; 1195 } catch (NamingException ne) { 1196 logger.debug("Login refused, server message : " + ne.getMessage()); 1197 dn = null; 1198 1199 invalidateCtx (privateCtx); 1200 1208 } 1209 return (dn != null); 1210 } 1211 1212 private void invalidateCtx (DirContext ctx) { 1213 if (ctx == null) { 1214 logger.debug ("Context passed is null, ignoring it..."); 1215 return; 1216 } 1217 try { 1218 ctx.close (); 1219 ctx = null; 1220 } catch (Exception e) { 1221 logger.warn (e); 1222 } 1223 } 1224 1225 private void invalidatePublicCtx () { 1226 try { 1227 invalidateCtx (getPublicContext(false)); 1228 } catch (NamingException ne) { 1229 logger.error("Couldn't invalidate public LDAP context", ne); 1230 } 1231 } 1232 1233 private DirContext connectToPublicDir () 1234 throws NamingException { 1235 if (((JahiaUserManagerRoutingService)ServicesRegistry 1237 .getInstance() 1238 .getJahiaUserManagerService()) 1239 .getServerList(PROVIDER_NAME) != null) { 1240 return connectToAllPublicDir(); 1241 } 1242 1243 logger.debug ("Attempting connection to LDAP repository on " + 1245 ldapProperties.getProperty (LDAP_URL_PROP) + "..."); 1246 1247 Hashtable publicEnv = new Hashtable (11); 1248 publicEnv.put (Context.INITIAL_CONTEXT_FACTORY, 1249 ldapProperties.getProperty (CONTEXT_FACTORY_PROP)); 1250 publicEnv.put (Context.PROVIDER_URL, 1251 ldapProperties.getProperty (LDAP_URL_PROP)); 1252 publicEnv.put (Context.SECURITY_AUTHENTICATION, 1253 ldapProperties.getProperty (AUTHENTIFICATION_MODE_PROP)); 1254 publicEnv.put (Context.SECURITY_PRINCIPAL, 1255 ldapProperties.getProperty (PUBLIC_BIND_DN_PROP)); 1256 publicEnv.put (Context.REFERRAL, 1257 ldapProperties.getProperty (LDAP_REFFERAL_PROP, "ignore")); 1258 if (ldapProperties.getProperty (PUBLIC_BIND_PASSWORD_PROP) != null) { 1259 logger.debug ("Using authentification mode to connect to public dir..."); 1260 publicEnv.put (Context.SECURITY_CREDENTIALS, 1261 ldapProperties.getProperty (PUBLIC_BIND_PASSWORD_PROP)); 1262 } 1263 1264 return new InitialDirContext (publicEnv); 1266 } 1267 1268 private DirContext connectToAllPublicDir () 1269 throws NamingException { 1270 DirContext ctx = null; 1271 TreeSet servers = ((JahiaUserManagerRoutingService)ServicesRegistry 1272 .getInstance() 1273 .getJahiaUserManagerService()) 1274 .getServerList(PROVIDER_NAME); 1275 1276 for (Iterator ite = servers.iterator(); ite.hasNext();) { 1277 ServerBean sb = (ServerBean) ite.next(); 1278 String sbUrl = (String )sb.getPublicConnectionParameters() 1279 .get(Context.PROVIDER_URL); 1280 1281 int tryNumber = 1; 1282 while (tryNumber <= sb.getMaxReconnection()) { 1283 logger.debug ("Attempting public connection " 1285 + tryNumber 1286 + " to LDAP repository on " 1287 + sbUrl 1288 + "..."); 1289 1290 try { 1292 ctx = new InitialDirContext (sb.getPublicConnectionParameters()); 1293 if (isContextValid(ctx)) 1294 return ctx; 1295 } catch (NamingException ne) { 1296 logger.error("Erreur while getting public context on " + sbUrl, ne); 1298 } 1299 tryNumber++; 1300 } 1301 } 1302 1303 if (ctx == null) { 1304 throw new NamingException("All servers used without success..."); 1305 } 1306 1307 return ctx; 1308 } 1309 1310 private DirContext connectToAllPrivateDir (String username, String password) 1311 throws NamingException { 1312 DirContext ctx = null; 1313 TreeSet servers = ((JahiaUserManagerRoutingService)ServicesRegistry 1314 .getInstance() 1315 .getJahiaUserManagerService()) 1316 .getServerList(PROVIDER_NAME); 1317 1318 for (Iterator ite = servers.iterator(); ite.hasNext();) { 1319 ServerBean sb = (ServerBean) ite.next(); 1320 Hashtable parameters = sb.getPrivateConnectionParameters( 1321 username, 1322 password); 1323 1324 String sbUrl = (String )parameters.get(Context.PROVIDER_URL); 1325 1326 int tryNumber = 1; 1327 while (tryNumber <= sb.getMaxReconnection()) { 1328 logger.debug ("Attempting private connection " 1330 + tryNumber 1331 + " to LDAP repository on " 1332 + sbUrl 1333 + "..."); 1334 1335 try { 1337 return new InitialDirContext (parameters); 1338 } catch (NamingSecurityException nse) { 1339 return null; 1341 } catch (NamingException ne) { 1342 } 1344 tryNumber++; 1345 } 1346 } 1347 1348 if (ctx == null) { 1349 throw new NamingException("All servers used without success..."); 1350 } 1351 1352 return ctx; 1353 } 1354 1355 private DirContext connectToPrivateDir (String dn, String personPassword) 1356 throws NamingException { 1357 if (((JahiaUserManagerRoutingService)ServicesRegistry 1359 .getInstance() 1360 .getJahiaUserManagerService()) 1361 .getServerList(PROVIDER_NAME) != null) { 1362 return connectToAllPrivateDir(dn, personPassword); 1363 } 1364 1365 Hashtable privateEnv = new Hashtable (11); 1367 privateEnv.put (Context.INITIAL_CONTEXT_FACTORY, 1368 ldapProperties.getProperty (CONTEXT_FACTORY_PROP)); 1369 privateEnv.put (Context.PROVIDER_URL, 1370 ldapProperties.getProperty (LDAP_URL_PROP)); 1371 privateEnv.put (Context.SECURITY_AUTHENTICATION, 1372 ldapProperties.getProperty (AUTHENTIFICATION_MODE_PROP)); 1373 privateEnv.put (Context.SECURITY_PRINCIPAL, dn ); 1374 privateEnv.put (Context.SECURITY_CREDENTIALS, 1375 personPassword); 1376 1377 return new InitialDirContext (privateEnv); 1379 } 1380 1381 1395 private NamingEnumeration getUsers (DirContext ctx, Properties filters, String searchBase, int scope) 1396 throws NamingException { 1397 if (ctx == null) { 1398 throw new NamingException("Context is null !"); 1399 } 1400 1401 StringBuffer filterString = new StringBuffer (); 1402 1403 if (filters == null) { 1404 filters = new Properties(); 1405 } 1406 1407 if (filters.containsKey("ldap.url")) { 1408 String url = filters.getProperty("ldap.url"); 1409 StringTokenizer st = new StringTokenizer(url.substring(8), "?"); 1410 String thisBase = st.nextToken(); 1411 String thisScope = st.nextToken(); 1412 String thisFilter = st.nextToken(); 1413 int intScope; 1414 if ("one".equalsIgnoreCase(thisScope)) { 1415 intScope = SearchControls.ONELEVEL_SCOPE; 1416 } else if ("base".equalsIgnoreCase(thisScope)) { 1417 intScope = SearchControls.OBJECT_SCOPE; 1418 } else { 1419 intScope = SearchControls.SUBTREE_SCOPE; 1420 } 1421 if (filters.containsKey("user.key")) { 1422 thisFilter = "(&("+ldapProperties.getProperty (UID_SEARCH_ATTRIBUTE_PROP)+"="+filters.get("user.key")+")"+thisFilter+")"; 1423 } 1424 return getUsers(ctx, thisFilter, thisBase, intScope); 1425 } else { 1426 filterString.append("(&(objectClass=" + ldapProperties.getProperty( 1427 USERS_OBJECTCLASS_ATTRIBUTE, "*") + ")"); 1428 1429 mapJahiaPropertiesToLDAP(filters); 1431 1432 1433 if (filters.size() > 1) { 1434 filterString.append("(|"); 1435 } 1436 1437 Enumeration filterKeys = filters.keys(); 1438 while (filterKeys.hasMoreElements()) { 1439 String filterName = (String ) filterKeys.nextElement(); 1440 String filterValue = filters.getProperty(filterName); 1441 filterValue = JahiaTools.replacePattern(filterValue, "\\", 1444 "\\5c"); 1445 filterValue = JahiaTools.replacePattern(filterValue, "(", 1446 "\\28"); 1447 filterValue = JahiaTools.replacePattern(filterValue, ")", 1448 "\\29"); 1449 1450 if ("*".equals(filterName)) { 1451 if (this.searchWildCardAttributeList != null) { 1454 if (this.searchWildCardAttributeList.size() > 1) { 1455 filterString.append("(|"); 1456 } 1457 Enumeration attributeEnum = this. 1458 searchWildCardAttributeList.elements(); 1459 while (attributeEnum.hasMoreElements()) { 1460 String curAttributeName = (String ) 1461 attributeEnum.nextElement(); 1462 filterString.append("("); 1463 filterString.append(curAttributeName); 1464 filterString.append("="); 1465 filterString.append(filterValue); 1466 filterString.append(")"); 1467 } 1468 if (this.searchWildCardAttributeList.size() > 1) { 1469 filterString.append(")"); 1470 } 1471 } 1472 } else { 1473 filterString.append("("); 1474 filterString.append(filterName); 1475 filterString.append("="); 1476 filterString.append(filterValue); 1477 filterString.append(")"); 1478 } 1479 } 1480 1481 if (filters.size() > 1) { 1482 filterString.append(")"); 1483 } 1484 1485 filterString.append(")"); 1486 1487 return getUsers(ctx, filterString.toString(), searchBase, scope); 1488 } 1489 } 1490 1491 private Attributes getUser (DirContext ctx, String dn) 1492 throws NamingException { 1493 try { 1494 return ctx.getAttributes(dn); 1495 } catch (javax.naming.NoInitialContextException nice) { 1496 logger.warn("Reconnection required", nice); 1497 return getUser(getPublicContext(true), dn); 1498 } catch (javax.naming.CannotProceedException cpe) { 1499 logger.warn("Reconnection required", cpe); 1500 return getUser(getPublicContext(true), dn); 1501 } catch (javax.naming.ServiceUnavailableException sue) { 1502 logger.warn("Reconnection required", sue); 1503 return getUser(getPublicContext(true), dn); 1504 } catch (javax.naming.TimeLimitExceededException tlee) { 1505 logger.warn("Reconnection required", tlee); 1506 return getUser(getPublicContext(true), dn); 1507 } catch (javax.naming.CommunicationException ce) { 1508 logger.warn("Reconnection required", ce); 1509 return getUser(getPublicContext(true), dn); 1510 } 1511 } 1512 1513 private NamingEnumeration getUsers (DirContext ctx, String filterString, String searchBase, int scope) 1514 throws NamingException { 1515 SearchControls searchCtl = new SearchControls (); 1517 searchCtl.setSearchScope (scope); 1518 int countLimit = Integer.parseInt ( 1519 ldapProperties.getProperty ( 1520 JahiaUserManagerLDAPProvider.SEARCH_COUNT_LIMIT_PROP)); 1521 searchCtl.setCountLimit (countLimit); 1522 logger.debug ("Using filter string [" + filterString.toString () + "]..."); 1523 try { 1524 return ctx.search ( 1525 searchBase, 1526 filterString.toString (), 1527 searchCtl); 1528 } catch (javax.naming.NoInitialContextException nice) { 1529 logger.warn("Reconnection required", nice); 1530 return getUsers(getPublicContext(true), filterString, searchBase, scope); 1531 } catch (javax.naming.CannotProceedException cpe) { 1532 logger.warn("Reconnection required", cpe); 1533 return getUsers(getPublicContext(true), filterString, searchBase, scope); 1534 } catch (javax.naming.ServiceUnavailableException sue) { 1535 logger.warn("Reconnection required", sue); 1536 return getUsers(getPublicContext(true), filterString, searchBase, scope); 1537 } catch (javax.naming.TimeLimitExceededException tlee) { 1538 logger.warn("Reconnection required", tlee); 1539 return getUsers(getPublicContext(true), filterString, searchBase, scope); 1540 } catch (javax.naming.CommunicationException ce) { 1541 logger.warn("Reconnection required", ce); 1542 return getUsers(getPublicContext(true), filterString, searchBase, scope); 1543 } 1544 1545 } 1546 1547 1559 private SearchResult getPublicUser (DirContext ctx, String prop, String val) 1560 throws NamingException { 1561 1562 Properties filters = new Properties(); 1563 1564 filters.setProperty(prop, val); 1565 NamingEnumeration answer = getUsers(ctx, filters, ldapProperties.getProperty (UID_SEARCH_NAME_PROP), SearchControls.SUBTREE_SCOPE); 1566 SearchResult sr = null; 1567 if (answer.hasMore()) { 1568 sr = (SearchResult ) answer.next (); 1571 boolean hasMore = false; 1572 try { 1573 hasMore = answer.hasMore (); 1574 } catch (PartialResultException pre) { 1575 logger.warn (pre); 1576 } 1577 1578 if (hasMore) { logger.debug( 1582 "Warning : multiple users with same UID in LDAP repository."); 1583 } 1584 } 1585 return sr; 1586 } 1587 1588 1592 1598 private void mapDBToJahiaProperties (UserProperties userProps, 1599 String usingUserKey) { 1600 1601 try { 1602 UserProperties dbProperties = JahiaUserDBUtils.getInstance(). 1603 getUserProperties( -1, 1604 PROVIDER_NAME, usingUserKey); 1605 userProps.putAll(dbProperties); 1606 } catch (JahiaException je) { 1607 logger.warn("SQL Exception occured : Could not read the user [" + 1608 usingUserKey + 1609 "] from the database for site LDAP user", je); 1610 } 1611 } 1612 1613 public String getUrl () { 1614 return ldapProperties.getProperty(LDAP_URL_PROP); 1615 } 1616 1617 1626 private String makeLIKEString (String input) { 1627 String result = JahiaTools.replacePattern(input, "*", "%"); 1628 result = JahiaTools.replacePattern(result, "'", "\\'"); 1629 result = JahiaTools.replacePattern(result, "\"", "\\\""); 1630 result = JahiaTools.replacePattern(result, "_", "\\_"); 1631 return result; 1632 } 1633 1634 1650 private synchronized Set searchLDAPUsersByDBProperties (int siteID, 1651 Properties searchCriterias) 1652 throws JahiaDatabaseException { 1653 Set userKeys = new HashSet(); 1654 1655 Connection dbConn = org.jahia.services.database.ConnectionDispenser. 1657 getConnection(); 1658 if (dbConn == null) { 1659 return userKeys; 1660 } 1661 1662 if (searchCriterias == null) { 1663 searchCriterias = new Properties(); 1664 searchCriterias.setProperty("*", "*"); 1665 } 1666 1667 boolean haveWildCardProperty = false; 1668 if (searchCriterias.getProperty("*") != null) { 1669 haveWildCardProperty = true; 1670 } 1671 1672 Statement statement = null; 1674 try { 1675 statement = dbConn.createStatement(); 1676 if (statement != null) { 1677 1678 StringBuffer query; 1679 1680 query = 1681 new StringBuffer ( 1682 "SELECT DISTINCT userkey_jahia_user_prop FROM jahia_user_prop WHERE provider_jahia_user_prop='"); 1683 query.append(PROVIDER_NAME); 1684 query.append("' AND "); 1685 Enumeration criteriaNames = searchCriterias.keys(); 1686 while (criteriaNames.hasMoreElements()) { 1687 String curCriteriaName = (String ) criteriaNames. 1688 nextElement(); 1689 String curCriteriaValue = makeLIKEString( 1690 searchCriterias.getProperty(curCriteriaName)); 1691 if ("*".equals(curCriteriaName)) { 1692 query.append( 1695 " value_jahia_user_prop LIKE '"); 1696 query.append(curCriteriaValue); 1697 query.append("' "); 1698 if (criteriaNames.hasMoreElements()) { 1699 query.append(" AND "); 1700 } 1701 } else { 1702 query.append( 1703 "(name_jahia_user_prop='"); 1704 query.append(makeLIKEString(curCriteriaName)); 1705 query.append( 1706 "' AND value_jahia_user_prop LIKE '"); 1707 query.append(curCriteriaValue); 1708 query.append("') "); 1709 if (criteriaNames.hasMoreElements()) { 1710 query.append(" AND "); 1711 } 1712 } 1713 } 1714 logger.debug("Executing query [" + query.toString() + "]"); 1715 1716 ResultSet rs = statement.executeQuery(query.toString()); 1717 if (rs != null) { 1718 while (rs.next()) { 1719 String name = rs.getString(1); 1720 if (name != null) { 1721 userKeys.add(name); 1722 } 1723 } 1724 } 1725 } 1726 } catch (SQLException ex) { 1727 logger.error("Error while searching users in site " + siteID, ex); 1728 } finally { 1729 closeStatement(statement); 1730 } 1731 1732 return userKeys; 1733 1734 } 1735 1736 private void closeStatement (Statement statement) 1738 throws JahiaDatabaseException { 1739 try { 1741 if (statement != null) { 1742 statement.close(); 1743 } 1744 } catch (SQLException sqlEx) { 1745 throw new JahiaDatabaseException( 1746 "Could not close a statement in JahiaDBUser", 1747 sqlEx, JahiaDatabaseException.ERROR_SEVERITY); 1748 } 1749 } 1750 1751} 1752 | Popular Tags |