List of usage examples for javax.naming.directory Attributes get
Attribute get(String attrID);
From source file:dk.magenta.ldap.LDAPMultiBaseUserRegistry.java
public Collection<NodeDescription> getGroups(Date modifiedSince) { // Work out whether the user and group trees are disjoint. This may allow us to optimize reverse DN // resolution. final Set<LdapName> groupDistinguishedNamePrefixes = new LinkedHashSet<>(); for (String groupSearchBase : this.groupSearchBases) { try {//from w ww .jav a 2 s .co m final LdapName groupDistinguishedNamePrefix = fixedLdapName(groupSearchBase.toLowerCase()); groupDistinguishedNamePrefixes.add(groupDistinguishedNamePrefix); } catch (InvalidNameException e) { Object[] params = { groupSearchBase.toLowerCase(), e.getLocalizedMessage() }; throw new AlfrescoRuntimeException("synchronization.err.ldap.search.base.invalid", params, e); } } final Set<LdapName> userDistinguishedNamePrefixes = new LinkedHashSet<>(); for (String userSearchBase : this.userSearchBases) { try { final LdapName userDistinguishedNamePrefix = fixedLdapName(userSearchBase.toLowerCase()); userDistinguishedNamePrefixes.add(userDistinguishedNamePrefix); } catch (InvalidNameException e) { Object[] params = { userSearchBase.toLowerCase(), e.getLocalizedMessage() }; throw new AlfrescoRuntimeException("synchronization.err.ldap.search.base.invalid", params, e); } } final Set<LdapName> distinctGroupDNPrefixes = new LinkedHashSet<>(groupDistinguishedNamePrefixes); final Set<LdapName> distinctUserDNPrefixes = new LinkedHashSet<>(userDistinguishedNamePrefixes); removeCommonPrefixedNamesFromSets(distinctGroupDNPrefixes, distinctUserDNPrefixes); // If there exist either distinct user DNs or group DNs, then the // sets are disjoint, and we may be able to recognize user or group // DNs without secondary lookup final boolean disjoint = !distinctUserDNPrefixes.isEmpty() || !distinctGroupDNPrefixes.isEmpty(); if (LDAPMultiBaseUserRegistry.logger.isDebugEnabled()) { if (disjoint) { LDAPMultiBaseUserRegistry.logger.debug("Distinct user " + "DN prefixes: " + distinctUserDNPrefixes); LDAPMultiBaseUserRegistry.logger .debug("Distinct group " + "DN prefixes: " + distinctGroupDNPrefixes); } } // Choose / generate the query String query; if (modifiedSince == null) { query = this.groupQuery; } else { query = MessageFormat.format(this.groupDifferentialQuery, this.timestampFormat.format(modifiedSince)); } // Run the query and process the results final Map<String, NodeDescription> lookup = new TreeMap<String, NodeDescription>(); processQuery(new SearchCallback() { // We get a whole new context to avoid interference with cookies from paged results private DirContext ctx = LDAPMultiBaseUserRegistry.this.ldapInitialContextFactory .getDefaultIntialDirContext(); public void process(SearchResult result) throws NamingException, ParseException { Attributes attributes = result.getAttributes(); Attribute gidAttribute = attributes.get(LDAPMultiBaseUserRegistry.this.groupIdAttributeName); if (gidAttribute == null) { if (LDAPMultiBaseUserRegistry.this.errorOnMissingGID) { Object[] params = { result.getNameInNamespace(), LDAPMultiBaseUserRegistry.this.groupIdAttributeName }; throw new AlfrescoRuntimeException("synchronization.err.ldap.get.group.id.missing", params); } else { LDAPMultiBaseUserRegistry.logger.warn("Missing GID on " + attributes); return; } } String groupShortName = gidAttribute.get(0).toString(); String gid = "GROUP_" + groupShortName; NodeDescription group = lookup.get(gid); if (group == null) { // Apply the mapped properties to the node description group = mapToNode(LDAPMultiBaseUserRegistry.this.groupAttributeMapping, LDAPMultiBaseUserRegistry.this.groupAttributeDefaults, result); // Make sure the "GROUP_" prefix is applied group.getProperties().put(ContentModel.PROP_AUTHORITY_NAME, gid); lookup.put(gid, group); } else if (LDAPMultiBaseUserRegistry.this.errorOnDuplicateGID) { throw new AlfrescoRuntimeException("Duplicate group id found for " + gid); } else { LDAPMultiBaseUserRegistry.logger .warn("Duplicate gid found for " + gid + " -> merging definitions"); } Set<String> childAssocs = group.getChildAssociations(); // Get the repeating (and possibly range restricted) member attribute Attribute memAttribute = getRangeRestrictedAttribute(attributes, LDAPMultiBaseUserRegistry.this.memberAttributeName); int nextStart = LDAPMultiBaseUserRegistry.this.attributeBatchSize; if (LDAPMultiBaseUserRegistry.logger.isDebugEnabled()) { LDAPMultiBaseUserRegistry.logger .debug("Processing group: " + gid + ", from source: " + group.getSourceId()); } // Loop until we get to the end of the range while (memAttribute != null) { for (int i = 0; i < memAttribute.size(); i++) { String attribute = (String) memAttribute.get(i); if (attribute != null && attribute.length() > 0) { try { // Attempt to parse the member attribute as a DN. If this fails we have a fallback // in the catch block LdapName distinguishedNameForComparison = fixedLdapName(attribute.toLowerCase()); Attribute nameAttribute; // If the user and group search bases are different we may be able to recognize user // and group DNs without a secondary lookup if (disjoint) { LdapName distinguishedName = fixedLdapName(attribute); Attributes nameAttributes = distinguishedName .getRdn(distinguishedName.size() - 1).toAttributes(); // Recognize user DNs if (nameStartsWithNameInSet(distinguishedNameForComparison, distinctUserDNPrefixes) && (nameAttribute = nameAttributes.get( LDAPMultiBaseUserRegistry.this.userIdAttributeName)) != null) { if (LDAPMultiBaseUserRegistry.logger.isDebugEnabled()) { LDAPMultiBaseUserRegistry.logger .debug("User DN recognized: " + nameAttribute.get()); } childAssocs.add((String) nameAttribute.get()); continue; } // Recognize group DNs if (nameStartsWithNameInSet(distinguishedNameForComparison, distinctGroupDNPrefixes) && (nameAttribute = nameAttributes.get( LDAPMultiBaseUserRegistry.this.groupIdAttributeName)) != null) { if (LDAPMultiBaseUserRegistry.logger.isDebugEnabled()) { LDAPMultiBaseUserRegistry.logger.debug( "Group DN recognized: " + "GROUP_" + nameAttribute.get()); } childAssocs.add("GROUP_" + nameAttribute.get()); continue; } } // If we can't determine the name and type from the DN alone, try a directory lookup if (nameStartsWithNameInSet(distinguishedNameForComparison, userDistinguishedNamePrefixes) || nameStartsWithNameInSet(distinguishedNameForComparison, groupDistinguishedNamePrefixes)) { try { Attributes childAttributes = this.ctx.getAttributes(jndiName(attribute), new String[] { "objectclass", LDAPMultiBaseUserRegistry.this.groupIdAttributeName, LDAPMultiBaseUserRegistry.this.userIdAttributeName }); Attribute objectClass = childAttributes.get("objectclass"); if (hasAttributeValue(objectClass, LDAPMultiBaseUserRegistry.this.personType)) { nameAttribute = childAttributes .get(LDAPMultiBaseUserRegistry.this.userIdAttributeName); if (nameAttribute == null) { if (LDAPMultiBaseUserRegistry.this.errorOnMissingUID) { throw new AlfrescoRuntimeException( "User missing user id attribute DN =" + attribute + " att = " + LDAPMultiBaseUserRegistry.this.userIdAttributeName); } else { LDAPMultiBaseUserRegistry.logger .warn("User missing user id attribute DN =" + attribute + " att = " + LDAPMultiBaseUserRegistry.this.userIdAttributeName); continue; } } if (LDAPMultiBaseUserRegistry.logger.isDebugEnabled()) { LDAPMultiBaseUserRegistry.logger .debug("User DN recognized by directory lookup: " + nameAttribute.get()); } childAssocs.add((String) nameAttribute.get()); continue; } else if (hasAttributeValue(objectClass, LDAPMultiBaseUserRegistry.this.groupType)) { nameAttribute = childAttributes .get(LDAPMultiBaseUserRegistry.this.groupIdAttributeName); if (nameAttribute == null) { if (LDAPMultiBaseUserRegistry.this.errorOnMissingGID) { Object[] params = { result.getNameInNamespace(), LDAPMultiBaseUserRegistry.this.groupIdAttributeName }; throw new AlfrescoRuntimeException( "synchronization.err.ldap.get.group.id.missing", params); } else { LDAPMultiBaseUserRegistry.logger .warn("Missing GID on " + childAttributes); continue; } } if (LDAPMultiBaseUserRegistry.logger.isDebugEnabled()) { LDAPMultiBaseUserRegistry.logger .debug("Group DN recognized by directory lookup: " + "GROUP_" + nameAttribute.get()); } childAssocs.add("GROUP_" + nameAttribute.get()); continue; } } catch (NamingException e) { // Unresolvable name if (LDAPMultiBaseUserRegistry.this.errorOnMissingMembers) { Object[] params = { groupShortName, attribute, e.getLocalizedMessage() }; throw new AlfrescoRuntimeException( "synchronization.err.ldap.group.member.missing.exception", params, e); } LDAPMultiBaseUserRegistry.logger.warn("Failed to resolve member of group '" + groupShortName + "' with distinguished name: " + attribute, e); continue; } } if (LDAPMultiBaseUserRegistry.this.errorOnMissingMembers) { Object[] params = { groupShortName, attribute }; throw new AlfrescoRuntimeException( "synchronization.err.ldap.group.member.missing", params); } LDAPMultiBaseUserRegistry.logger.warn("Failed to resolve member of group '" + groupShortName + "' with distinguished name: " + attribute); } catch (InvalidNameException e) { // The member attribute didn't parse as a DN. So assume we have a group class like // posixGroup (FDS) that directly lists user names if (LDAPMultiBaseUserRegistry.logger.isDebugEnabled()) { LDAPMultiBaseUserRegistry.logger .debug("Member DN recognized as posixGroup: " + attribute); } childAssocs.add(attribute); } } } // If we are using attribute matching and we haven't got to the end (indicated by an asterisk), // fetch the next batch if (nextStart > 0 && !LDAPMultiBaseUserRegistry.PATTERN_RANGE_END .matcher(memAttribute.getID().toLowerCase()).find()) { Attributes childAttributes = this.ctx.getAttributes(jndiName(result.getNameInNamespace()), new String[] { LDAPMultiBaseUserRegistry.this.memberAttributeName + ";range=" + nextStart + '-' + (nextStart + LDAPMultiBaseUserRegistry.this.attributeBatchSize - 1) }); memAttribute = getRangeRestrictedAttribute(childAttributes, LDAPMultiBaseUserRegistry.this.memberAttributeName); nextStart += LDAPMultiBaseUserRegistry.this.attributeBatchSize; } else { memAttribute = null; } } } public void close() throws NamingException { this.ctx.close(); } }, this.groupSearchBases, query, this.groupKeys.getFirst()); if (LDAPMultiBaseUserRegistry.logger.isDebugEnabled()) { LDAPMultiBaseUserRegistry.logger.debug("Found " + lookup.size()); } return lookup.values(); }
From source file:org.josso.gateway.identity.service.store.ldap.LDAPIdentityStore.java
/** * Fetch the Ldap user attributes to be used as credentials. * * @param uid the user id (or lookup value) for whom credentials are required * @return the hash map containing user credentials as name/value pairs * @throws NamingException LDAP error obtaining user credentials. * @throws IOException /*from w ww .j a v a 2 s. com*/ */ protected HashMap selectCredentials(String uid, CredentialProvider cp) throws NamingException, IOException { HashMap credentialResultSet = new HashMap(); InitialLdapContext ctx = createLdapInitialContext(false); StartTlsResponse tls = null; if (getEnableStartTls()) { tls = startTls(ctx); } String schemeName = null; if (cp instanceof AuthenticationScheme) { schemeName = ((AuthenticationScheme) cp).getName(); } String principalLookupAttrName = this.getPrincipalLookupAttributeID(); if (principalLookupAttrName == null || principalLookupAttrName.trim().equals("") || !"strong-authentication".equals(schemeName)) { principalLookupAttrName = this.getPrincipalUidAttributeID(); } String usersCtxDN = this.getUsersCtxDN(); // BasicAttributes matchAttrs = new BasicAttributes(true); // matchAttrs.put(principalUidAttrName, uid); String credentialQueryString = getCredentialQueryString(); HashMap credentialQueryMap = parseQueryString(credentialQueryString); Iterator i = credentialQueryMap.keySet().iterator(); List credentialAttrList = new ArrayList(); while (i.hasNext()) { String o = (String) i.next(); credentialAttrList.add(o); } String[] credentialAttr = (String[]) credentialAttrList.toArray(new String[credentialAttrList.size()]); try { // NamingEnumeration answer = ctx.search(usersCtxDN, matchAttrs, credentialAttr); // This gives more control over search behavior : NamingEnumeration answer = ctx.search(usersCtxDN, "(&(" + principalLookupAttrName + "=" + uid + "))", getSearchControls()); while (answer.hasMore()) { SearchResult sr = (SearchResult) answer.next(); Attributes attrs = sr.getAttributes(); String userDN = sr.getNameInNamespace(); if (logger.isDebugEnabled()) logger.debug("Processing results for entry '" + userDN + "'"); for (int j = 0; j < credentialAttr.length; j++) { if (attrs.get(credentialAttr[j]) == null) continue; //Object credentialObject = attrs.get(credentialAttr[j]).get(); String credentialName = (String) credentialQueryMap.get(credentialAttr[j]); String credentialValue = null; Attribute attr = attrs.get(credentialAttr[j]); NamingEnumeration attrEnum = attr.getAll(); while (attrEnum.hasMore()) { Object credentialObject = attrEnum.next(); if (credentialObject == null) continue; if (logger.isDebugEnabled()) logger.debug("Found user credential '" + credentialName + "' of type '" + credentialObject.getClass().getName() + "" + (credentialObject.getClass().isArray() ? "[" + Array.getLength(credentialObject) + "]" : "") + "'"); // if the attribute value is an array, cast it to byte[] and then convert to // String using proper encoding if (credentialObject.getClass().isArray()) { try { // Try to create a UTF-8 String, we use java.nio to handle errors in a better way. // If the byte[] cannot be converted to UTF-8, we're using the credentialObject as is. byte[] credentialData = (byte[]) credentialObject; ByteBuffer in = ByteBuffer.allocate(credentialData.length); in.put(credentialData); in.flip(); Charset charset = Charset.forName("UTF-8"); CharsetDecoder decoder = charset.newDecoder(); CharBuffer charBuffer = decoder.decode(in); credentialValue = charBuffer.toString(); } catch (CharacterCodingException e) { if (logger.isDebugEnabled()) logger.debug("Can't convert credential value to String using UTF-8"); } } else if (credentialObject instanceof String) { // The credential value must be a String ... credentialValue = (String) credentialObject; } // Check what do we have ... List credentials = (List) credentialResultSet.get(credentialName); if (credentials == null) { credentials = new ArrayList(); } if (credentialValue != null) { // Remove any schema information from the credential value, like the {md5} prefix for passwords. credentialValue = getSchemeFreeValue(credentialValue); credentials.add(credentialValue); } else { // We have a binary credential, leave it as it is ... probably binary value. credentials.add(credentialObject); } credentialResultSet.put(credentialName, credentials); if (logger.isDebugEnabled()) logger.debug("Found user credential '" + credentialName + "' with value '" + (credentialValue != null ? credentialValue : credentialObject) + "'"); } } } } catch (NamingException e) { if (logger.isDebugEnabled()) logger.debug("Failed to locate user", e); } finally { // Close the context to release the connection if (tls != null) { tls.close(); } ctx.close(); } return credentialResultSet; }
From source file:org.cggh.repo.security.sync.ldap.LDAPUserRegistry.java
public Collection<NodeDescription> getGroups(Date modifiedSince) { // Work out whether the user and group trees are disjoint. This may allow us to optimize reverse DN // resolution. final LdapName groupDistinguishedNamePrefix; try {//from w w w .j a v a 2 s . c o m groupDistinguishedNamePrefix = fixedLdapName(this.groupSearchBase.toLowerCase()); } catch (InvalidNameException e) { Object[] params = { this.groupSearchBase.toLowerCase(), e.getLocalizedMessage() }; throw new AlfrescoRuntimeException("synchronization.err.ldap.search.base.invalid", params, e); } final LdapName userDistinguishedNamePrefix; try { userDistinguishedNamePrefix = fixedLdapName(this.userSearchBase.toLowerCase()); } catch (InvalidNameException e) { Object[] params = { this.userSearchBase.toLowerCase(), e.getLocalizedMessage() }; throw new AlfrescoRuntimeException("synchronization.err.ldap.search.base.invalid", params, e); } final boolean disjoint = !groupDistinguishedNamePrefix.startsWith(userDistinguishedNamePrefix) && !userDistinguishedNamePrefix.startsWith(groupDistinguishedNamePrefix); // Choose / generate the query String query; if (modifiedSince == null) { query = this.groupQuery; } else { query = MessageFormat.format(this.groupDifferentialQuery, this.timestampFormat.format(modifiedSince)); } // Run the query and process the results final Map<String, NodeDescription> lookup = new TreeMap<String, NodeDescription>(); processQuery(new AbstractSearchCallback() { // We get a whole new context to avoid interference with cookies from paged results private DirContext ctx = LDAPUserRegistry.this.ldapInitialContextFactory.getDefaultIntialDirContext(); protected void doProcess(SearchResult result) throws NamingException, ParseException { Attributes attributes = result.getAttributes(); Attribute gidAttribute = attributes.get(LDAPUserRegistry.this.groupIdAttributeName); if (gidAttribute == null) { if (LDAPUserRegistry.this.errorOnMissingGID) { Object[] params = { result.getNameInNamespace(), LDAPUserRegistry.this.groupIdAttributeName }; throw new AlfrescoRuntimeException("synchronization.err.ldap.get.group.id.missing", params); } else { LDAPUserRegistry.logger.warn( "Missing GID2 on " + result.getNameInNamespace() + " attributes:" + attributes); return; } } String groupShortName = gidAttribute.get(0).toString(); String gid = "GROUP_" + groupShortName; NodeDescription group = lookup.get(gid); if (group == null) { // Apply the mapped properties to the node description group = mapToNode(LDAPUserRegistry.this.groupAttributeMapping, LDAPUserRegistry.this.groupAttributeDefaults, result); // Make sure the "GROUP_" prefix is applied group.getProperties().put(ContentModel.PROP_AUTHORITY_NAME, gid); lookup.put(gid, group); } else if (LDAPUserRegistry.this.errorOnDuplicateGID) { throw new AlfrescoRuntimeException("Duplicate group id found for " + gid); } else { LDAPUserRegistry.logger.warn("Duplicate gid found for " + gid + " -> merging definitions"); } Set<String> childAssocs = group.getChildAssociations(); // Get the repeating (and possibly range restricted) member attribute Attribute memAttribute = getRangeRestrictedAttribute(attributes, LDAPUserRegistry.this.memberAttributeName); int nextStart = LDAPUserRegistry.this.attributeBatchSize; if (LDAPUserRegistry.logger.isDebugEnabled()) { LDAPUserRegistry.logger .debug("Processing group: " + gid + ", from source: " + group.getSourceId()); } // Loop until we get to the end of the range while (memAttribute != null) { for (int i = 0; i < memAttribute.size(); i++) { String attribute = (String) memAttribute.get(i); if (attribute != null && attribute.length() > 0) { try { // Attempt to parse the member attribute as a DN. If this fails we have a fallback // in the catch block LdapName distinguishedNameForComparison = fixedLdapName(attribute.toLowerCase()); Attribute nameAttribute; // If the user and group search bases are different we may be able to recognize user // and group DNs without a secondary lookup if (disjoint) { LdapName distinguishedName = fixedLdapName(attribute); Attributes nameAttributes = distinguishedName .getRdn(distinguishedName.size() - 1).toAttributes(); // Recognize user DNs if (distinguishedNameForComparison.startsWith(userDistinguishedNamePrefix) && (nameAttribute = nameAttributes .get(LDAPUserRegistry.this.userIdAttributeName)) != null) { if (LDAPUserRegistry.logger.isDebugEnabled()) { LDAPUserRegistry.logger .debug("User DN recognized: " + nameAttribute.get()); } childAssocs.add((String) nameAttribute.get()); continue; } // Recognize group DNs if (distinguishedNameForComparison.startsWith(groupDistinguishedNamePrefix) && (nameAttribute = nameAttributes .get(LDAPUserRegistry.this.groupIdAttributeName)) != null) { if (LDAPUserRegistry.logger.isDebugEnabled()) { LDAPUserRegistry.logger.debug( "Group DN recognized: " + "GROUP_" + nameAttribute.get()); } childAssocs.add("GROUP_" + nameAttribute.get()); continue; } } // If we can't determine the name and type from the DN alone, try a directory lookup if (distinguishedNameForComparison.startsWith(userDistinguishedNamePrefix) || distinguishedNameForComparison .startsWith(groupDistinguishedNamePrefix)) { try { Attributes childAttributes = this.ctx.getAttributes(jndiName(attribute), new String[] { "objectclass", LDAPUserRegistry.this.groupIdAttributeName, LDAPUserRegistry.this.userIdAttributeName }); Attribute objectClass = childAttributes.get("objectclass"); if (hasAttributeValue(objectClass, LDAPUserRegistry.this.personType)) { nameAttribute = childAttributes .get(LDAPUserRegistry.this.userIdAttributeName); if (nameAttribute == null) { if (LDAPUserRegistry.this.errorOnMissingUID) { throw new AlfrescoRuntimeException( "User missing user id attribute DN =" + attribute + " att = " + LDAPUserRegistry.this.userIdAttributeName); } else { LDAPUserRegistry.logger .warn("User missing user id attribute DN =" + attribute + " att = " + LDAPUserRegistry.this.userIdAttributeName); continue; } } if (LDAPUserRegistry.logger.isDebugEnabled()) { LDAPUserRegistry.logger .debug("User DN recognized by directory lookup: " + nameAttribute.get()); } childAssocs.add((String) nameAttribute.get()); continue; } else if (hasAttributeValue(objectClass, LDAPUserRegistry.this.groupType)) { nameAttribute = childAttributes .get(LDAPUserRegistry.this.groupIdAttributeName); if (nameAttribute == null) { if (LDAPUserRegistry.this.errorOnMissingGID) { Object[] params = { result.getNameInNamespace(), LDAPUserRegistry.this.groupIdAttributeName }; throw new AlfrescoRuntimeException( "synchronization.err.ldap.get.group.id.missing", params); } else { LDAPUserRegistry.logger.warn( "Missing GID3 on " + distinguishedNameForComparison + " attributes:" + childAttributes); continue; } } if (LDAPUserRegistry.logger.isDebugEnabled()) { LDAPUserRegistry.logger .debug("Group DN recognized by directory lookup: " + "GROUP_" + nameAttribute.get()); } childAssocs.add("GROUP_" + nameAttribute.get()); continue; } } catch (NamingException e) { // Unresolvable name if (LDAPUserRegistry.this.errorOnMissingMembers) { Object[] params = { groupShortName, attribute, e.getLocalizedMessage() }; throw new AlfrescoRuntimeException( "synchronization.err.ldap.group.member.missing.exception", params, e); } LDAPUserRegistry.logger.warn("Failed to resolve member of group '" + groupShortName + "' with distinguished name: " + attribute, e); continue; } } if (LDAPUserRegistry.this.errorOnMissingMembers) { Object[] params = { groupShortName, attribute }; throw new AlfrescoRuntimeException( "synchronization.err.ldap.group.member.missing", params); } LDAPUserRegistry.logger.warn("Failed to resolve member of group '" + groupShortName + "' with distinguished name: " + attribute); } catch (InvalidNameException e) { // The member attribute didn't parse as a DN. So assume we have a group class like // posixGroup (FDS) that directly lists user names if (LDAPUserRegistry.logger.isDebugEnabled()) { LDAPUserRegistry.logger .debug("Member DN recognized as posixGroup: " + attribute); } childAssocs.add(attribute); } } } // If we are using attribute matching and we haven't got to the end (indicated by an asterisk), // fetch the next batch if (nextStart > 0 && !LDAPUserRegistry.PATTERN_RANGE_END .matcher(memAttribute.getID().toLowerCase()).find()) { Attributes childAttributes = this.ctx.getAttributes(jndiName(result.getNameInNamespace()), new String[] { LDAPUserRegistry.this.memberAttributeName + ";range=" + nextStart + '-' + (nextStart + LDAPUserRegistry.this.attributeBatchSize - 1) }); memAttribute = getRangeRestrictedAttribute(childAttributes, LDAPUserRegistry.this.memberAttributeName); nextStart += LDAPUserRegistry.this.attributeBatchSize; } else { memAttribute = null; } } } public void close() throws NamingException { this.ctx.close(); } }, this.groupSearchBase, query, this.groupKeys.getFirst()); if (LDAPUserRegistry.logger.isDebugEnabled()) { LDAPUserRegistry.logger.debug("Found " + lookup.size()); } return lookup.values(); }
From source file:org.alfresco.repo.security.sync.ldap.LDAPUserRegistry.java
public Collection<NodeDescription> getGroups(Date modifiedSince) { // Work out whether the user and group trees are disjoint. This may allow us to optimize reverse DN // resolution. final LdapName groupDistinguishedNamePrefix; try {//from www . j a v a 2s. c o m groupDistinguishedNamePrefix = fixedLdapName(this.groupSearchBase.toLowerCase()); } catch (InvalidNameException e) { Object[] params = { this.groupSearchBase.toLowerCase(), e.getLocalizedMessage() }; throw new AlfrescoRuntimeException("synchronization.err.ldap.search.base.invalid", params, e); } final LdapName userDistinguishedNamePrefix; try { userDistinguishedNamePrefix = fixedLdapName(this.userSearchBase.toLowerCase()); } catch (InvalidNameException e) { Object[] params = { this.userSearchBase.toLowerCase(), e.getLocalizedMessage() }; throw new AlfrescoRuntimeException("synchronization.err.ldap.search.base.invalid", params, e); } final boolean disjoint = !groupDistinguishedNamePrefix.startsWith(userDistinguishedNamePrefix) && !userDistinguishedNamePrefix.startsWith(groupDistinguishedNamePrefix); // Choose / generate the query String query; if (modifiedSince == null) { query = this.groupQuery; } else { query = MessageFormat.format(this.groupDifferentialQuery, this.timestampFormat.format(modifiedSince)); } // Run the query and process the results final Map<String, NodeDescription> lookup = new TreeMap<String, NodeDescription>(); processQuery(new AbstractSearchCallback() { // We get a whole new context to avoid interference with cookies from paged results private DirContext ctx = LDAPUserRegistry.this.ldapInitialContextFactory.getDefaultIntialDirContext(); protected void doProcess(SearchResult result) throws NamingException, ParseException { Attributes attributes = result.getAttributes(); Attribute gidAttribute = attributes.get(LDAPUserRegistry.this.groupIdAttributeName); if (gidAttribute == null) { if (LDAPUserRegistry.this.errorOnMissingGID) { Object[] params = { result.getNameInNamespace(), LDAPUserRegistry.this.groupIdAttributeName }; throw new AlfrescoRuntimeException("synchronization.err.ldap.get.group.id.missing", params); } else { LDAPUserRegistry.logger.warn("Missing GID on " + attributes); return; } } String groupShortName = gidAttribute.get(0).toString(); String gid = "GROUP_" + groupShortName; NodeDescription group = lookup.get(gid); if (group == null) { // Apply the mapped properties to the node description group = mapToNode(LDAPUserRegistry.this.groupAttributeMapping, LDAPUserRegistry.this.groupAttributeDefaults, result); // Make sure the "GROUP_" prefix is applied group.getProperties().put(ContentModel.PROP_AUTHORITY_NAME, gid); lookup.put(gid, group); } else if (LDAPUserRegistry.this.errorOnDuplicateGID) { throw new AlfrescoRuntimeException("Duplicate group id found for " + gid); } else { LDAPUserRegistry.logger.warn("Duplicate gid found for " + gid + " -> merging definitions"); } Set<String> childAssocs = group.getChildAssociations(); // Get the repeating (and possibly range restricted) member attribute Attribute memAttribute = getRangeRestrictedAttribute(attributes, LDAPUserRegistry.this.memberAttributeName); int nextStart = LDAPUserRegistry.this.attributeBatchSize; if (LDAPUserRegistry.logger.isDebugEnabled()) { LDAPUserRegistry.logger .debug("Processing group: " + gid + ", from source: " + group.getSourceId()); } // Loop until we get to the end of the range while (memAttribute != null) { for (int i = 0; i < memAttribute.size(); i++) { String attribute = (String) memAttribute.get(i); if (attribute != null && attribute.length() > 0) { try { // Attempt to parse the member attribute as a DN. If this fails we have a fallback // in the catch block LdapName distinguishedNameForComparison = fixedLdapName(attribute.toLowerCase()); Attribute nameAttribute; // If the user and group search bases are different we may be able to recognize user // and group DNs without a secondary lookup if (disjoint) { LdapName distinguishedName = fixedLdapName(attribute); Attributes nameAttributes = distinguishedName .getRdn(distinguishedName.size() - 1).toAttributes(); // Recognize user DNs if (distinguishedNameForComparison.startsWith(userDistinguishedNamePrefix) && (nameAttribute = nameAttributes .get(LDAPUserRegistry.this.userIdAttributeName)) != null) { if (LDAPUserRegistry.logger.isDebugEnabled()) { LDAPUserRegistry.logger .debug("User DN recognized: " + nameAttribute.get()); } childAssocs.add((String) nameAttribute.get()); continue; } // Recognize group DNs if (distinguishedNameForComparison.startsWith(groupDistinguishedNamePrefix) && (nameAttribute = nameAttributes .get(LDAPUserRegistry.this.groupIdAttributeName)) != null) { if (LDAPUserRegistry.logger.isDebugEnabled()) { LDAPUserRegistry.logger.debug( "Group DN recognized: " + "GROUP_" + nameAttribute.get()); } childAssocs.add("GROUP_" + nameAttribute.get()); continue; } } // If we can't determine the name and type from the DN alone, try a directory lookup if (distinguishedNameForComparison.startsWith(userDistinguishedNamePrefix) || distinguishedNameForComparison .startsWith(groupDistinguishedNamePrefix)) { try { Attributes childAttributes = this.ctx.getAttributes(jndiName(attribute), new String[] { "objectclass", LDAPUserRegistry.this.groupIdAttributeName, LDAPUserRegistry.this.userIdAttributeName }); Attribute objectClass = childAttributes.get("objectclass"); if (hasAttributeValue(objectClass, LDAPUserRegistry.this.personType)) { nameAttribute = childAttributes .get(LDAPUserRegistry.this.userIdAttributeName); if (nameAttribute == null) { if (LDAPUserRegistry.this.errorOnMissingUID) { throw new AlfrescoRuntimeException( "User missing user id attribute DN =" + attribute + " att = " + LDAPUserRegistry.this.userIdAttributeName); } else { LDAPUserRegistry.logger .warn("User missing user id attribute DN =" + attribute + " att = " + LDAPUserRegistry.this.userIdAttributeName); continue; } } if (LDAPUserRegistry.logger.isDebugEnabled()) { LDAPUserRegistry.logger .debug("User DN recognized by directory lookup: " + nameAttribute.get()); } childAssocs.add((String) nameAttribute.get()); continue; } else if (hasAttributeValue(objectClass, LDAPUserRegistry.this.groupType)) { nameAttribute = childAttributes .get(LDAPUserRegistry.this.groupIdAttributeName); if (nameAttribute == null) { if (LDAPUserRegistry.this.errorOnMissingGID) { Object[] params = { result.getNameInNamespace(), LDAPUserRegistry.this.groupIdAttributeName }; throw new AlfrescoRuntimeException( "synchronization.err.ldap.get.group.id.missing", params); } else { LDAPUserRegistry.logger .warn("Missing GID on " + childAttributes); continue; } } if (LDAPUserRegistry.logger.isDebugEnabled()) { LDAPUserRegistry.logger .debug("Group DN recognized by directory lookup: " + "GROUP_" + nameAttribute.get()); } childAssocs.add("GROUP_" + nameAttribute.get()); continue; } } catch (NamingException e) { // Unresolvable name if (LDAPUserRegistry.this.errorOnMissingMembers) { Object[] params = { groupShortName, attribute, e.getLocalizedMessage() }; throw new AlfrescoRuntimeException( "synchronization.err.ldap.group.member.missing.exception", params, e); } LDAPUserRegistry.logger.warn("Failed to resolve member of group '" + groupShortName + "' with distinguished name: " + attribute, e); continue; } } if (LDAPUserRegistry.this.errorOnMissingMembers) { Object[] params = { groupShortName, attribute }; throw new AlfrescoRuntimeException( "synchronization.err.ldap.group.member.missing", params); } LDAPUserRegistry.logger.warn("Failed to resolve member of group '" + groupShortName + "' with distinguished name: " + attribute); } catch (InvalidNameException e) { // The member attribute didn't parse as a DN. So assume we have a group class like // posixGroup (FDS) that directly lists user names if (LDAPUserRegistry.logger.isDebugEnabled()) { LDAPUserRegistry.logger .debug("Member DN recognized as posixGroup: " + attribute); } childAssocs.add(attribute); } } } // If we are using attribute matching and we haven't got to the end (indicated by an asterisk), // fetch the next batch if (nextStart > 0 && !LDAPUserRegistry.PATTERN_RANGE_END .matcher(memAttribute.getID().toLowerCase()).find()) { Attributes childAttributes = this.ctx.getAttributes(jndiName(result.getNameInNamespace()), new String[] { LDAPUserRegistry.this.memberAttributeName + ";range=" + nextStart + '-' + (nextStart + LDAPUserRegistry.this.attributeBatchSize - 1) }); memAttribute = getRangeRestrictedAttribute(childAttributes, LDAPUserRegistry.this.memberAttributeName); nextStart += LDAPUserRegistry.this.attributeBatchSize; } else { memAttribute = null; } } } public void close() throws NamingException { this.ctx.close(); } }, this.groupSearchBase, query, this.groupKeys.getFirst()); if (LDAPUserRegistry.logger.isDebugEnabled()) { LDAPUserRegistry.logger.debug("Found " + lookup.size()); } return lookup.values(); }
From source file:org.nuxeo.ecm.directory.ldap.LDAPReference.java
protected String getIdForDn(LDAPSession session, String dn) { // the entry id is not based on the rdn, we thus need to // fetch the LDAP entry to grab it String[] attributeIdsToCollect = { session.idAttribute }; Attributes entry; try {// w ww. j a va 2 s . c om if (log.isDebugEnabled()) { log.debug(String.format( "LDAPReference.getIdForDn(session, %s): LDAP get dn='%s'" + " attribute ids to collect='%s' [%s]", dn, dn, StringUtils.join(attributeIdsToCollect, ", "), this)); } Name name = new CompositeName().add(dn); entry = session.dirContext.getAttributes(name, attributeIdsToCollect); } catch (NamingException e) { return null; } // NXP-2461: check that id field is filled Attribute attr = entry.get(session.idAttribute); if (attr != null) { try { return attr.get().toString(); } catch (NamingException e) { } } return null; }
From source file:org.nuxeo.ecm.directory.ldap.LDAPSession.java
@Override @SuppressWarnings("unchecked") public void updateEntry(DocumentModel docModel) { checkPermission(SecurityConstants.WRITE); List<String> updateList = new ArrayList<String>(); List<String> referenceFieldList = new LinkedList<String>(); try {//from w w w. j a va 2s . co m for (String fieldName : schemaFieldMap.keySet()) { if (!docModel.getPropertyObject(schemaName, fieldName).isDirty()) { continue; } if (getDirectory().isReference(fieldName)) { referenceFieldList.add(fieldName); } else { updateList.add(fieldName); } } if (!isReadOnlyEntry(docModel) && !updateList.isEmpty()) { Attributes attrs = new BasicAttributes(); SearchResult ldapEntry = getLdapEntry(docModel.getId()); if (ldapEntry == null) { throw new DirectoryException(docModel.getId() + " not found"); } Attributes oldattrs = ldapEntry.getAttributes(); String dn = ldapEntry.getNameInNamespace(); Attributes attrsToDel = new BasicAttributes(); for (String f : updateList) { Object value = docModel.getProperty(schemaName, f); String backendField = getDirectory().getFieldMapper().getBackendField(f); if (LDAPDirectory.DN_SPECIAL_ATTRIBUTE_KEY.equals(backendField)) { // skip special LDAP DN field that is readonly log.warn(String.format("field %s is mapped to read only DN field: ignored", f)); continue; } if (value == null || value.equals("")) { Attribute objectClasses = oldattrs.get("objectClass"); Attribute attr; if (getMandatoryAttributes(objectClasses).contains(backendField)) { attr = new BasicAttribute(backendField); // XXX: this might fail if the mandatory attribute // is typed integer for instance attr.add(" "); attrs.put(attr); } else if (oldattrs.get(backendField) != null) { attr = new BasicAttribute(backendField); attr.add(oldattrs.get(backendField).get()); attrsToDel.put(attr); } } else if (f.equals(getPasswordField())) { // The password has been updated, it has to be encrypted Attribute attr = new BasicAttribute(backendField); attr.add(PasswordHelper.hashPassword((String) value, passwordHashAlgorithm)); attrs.put(attr); } else { attrs.put(getAttributeValue(f, value)); } } if (log.isDebugEnabled()) { log.debug(String.format("LDAPSession.updateEntry(%s): LDAP modifyAttributes dn='%s' " + "mod_op='REMOVE_ATTRIBUTE' attr='%s' [%s]", docModel, dn, attrsToDel, this)); } dirContext.modifyAttributes(dn, DirContext.REMOVE_ATTRIBUTE, attrsToDel); if (log.isDebugEnabled()) { log.debug(String.format("LDAPSession.updateEntry(%s): LDAP modifyAttributes dn='%s' " + "mod_op='REPLACE_ATTRIBUTE' attr='%s' [%s]", docModel, dn, attrs, this)); } dirContext.modifyAttributes(dn, DirContext.REPLACE_ATTRIBUTE, attrs); } // update reference fields for (String referenceFieldName : referenceFieldList) { List<Reference> references = directory.getReferences(referenceFieldName); if (references.size() > 1) { // not supported } else { Reference reference = references.get(0); List<String> targetIds = (List<String>) docModel.getProperty(schemaName, referenceFieldName); reference.setTargetIdsForSource(docModel.getId(), targetIds); } } } catch (NamingException e) { handleException(e, "updateEntry failed:"); } getDirectory().invalidateCaches(); }
From source file:org.nuxeo.ecm.directory.ldap.LDAPReference.java
/** * Optimized method to spare a LDAP request when the caller is a LDAPSession object that has already fetched the * LDAP Attribute instances./* w w w. j a v a 2s. co m*/ * <p> * This method should return the same results as the sister method: org.nuxeo * .ecm.directory.Reference#getTargetIdsForSource(java.lang.String) * * @return target reference ids * @throws DirectoryException */ public List<String> getLdapTargetIds(Attributes attributes) throws DirectoryException { Set<String> targetIds = new TreeSet<>(); LDAPDirectory ldapTargetDirectory = (LDAPDirectory) getTargetDirectory(); LDAPDirectoryDescriptor targetDirconfig = getTargetDirectoryDescriptor(); String emptyRefMarker = ldapTargetDirectory.getDescriptor().getEmptyRefMarker(); try (LDAPSession targetSession = (LDAPSession) ldapTargetDirectory.getSession()) { String baseDn = pseudoNormalizeDn(targetDirconfig.getSearchBaseDn()); // step #1: fetch ids referenced by static attributes String staticAttributeId = getStaticAttributeId(); Attribute staticAttribute = null; if (staticAttributeId != null) { staticAttribute = attributes.get(staticAttributeId); } if (staticAttribute != null && !staticAttributeIdIsDn) { NamingEnumeration<?> staticContent = staticAttribute.getAll(); try { while (staticContent.hasMore()) { String value = staticContent.next().toString(); if (!emptyRefMarker.equals(value)) { targetIds.add(value); } } } finally { staticContent.close(); } } if (staticAttribute != null && staticAttributeIdIsDn) { NamingEnumeration<?> targetDns = staticAttribute.getAll(); try { while (targetDns.hasMore()) { String targetDn = targetDns.next().toString(); if (!pseudoNormalizeDn(targetDn).endsWith(baseDn)) { // optim: avoid network connections when obvious if (log.isTraceEnabled()) { log.trace(String.format("ignoring: dn='%s' (does not match '%s') for '%s'", targetDn, baseDn, this)); } continue; } // find the id of the referenced entry String id = null; if (targetSession.rdnMatchesIdField()) { // optim: do not fetch the entry to get its true id // but // guess it by reading the targetDn LdapName name = new LdapName(targetDn); String rdn = name.get(name.size() - 1); int pos = rdn.indexOf("="); id = rdn.substring(pos + 1); } else { id = getIdForDn(targetSession, targetDn); if (id == null) { log.warn(String.format( "ignoring target '%s' (missing attribute '%s') while resolving reference '%s'", targetDn, targetSession.idAttribute, this)); continue; } } if (forceDnConsistencyCheck) { // check that the referenced entry is actually part // of // the target directory (takes care of the filters // and // the scope) // this check can be very expensive on large groups // and thus not enabled by default if (!targetSession.hasEntry(id)) { if (log.isTraceEnabled()) { log.trace(String.format( "ignoring target '%s' when resolving '%s' (not part of target" + " directory by forced DN consistency check)", targetDn, this)); } continue; } } // NXP-2461: check that id field is filled if (id != null) { targetIds.add(id); } } } finally { targetDns.close(); } } // step #2: fetched dynamically referenced ids String dynamicAttributeId = this.dynamicAttributeId; Attribute dynamicAttribute = null; if (dynamicAttributeId != null) { dynamicAttribute = attributes.get(dynamicAttributeId); } if (dynamicAttribute != null) { NamingEnumeration<?> rawldapUrls = dynamicAttribute.getAll(); try { while (rawldapUrls.hasMore()) { LdapURL ldapUrl = new LdapURL(rawldapUrls.next().toString()); String linkDn = pseudoNormalizeDn(ldapUrl.getDN()); String directoryDn = pseudoNormalizeDn(targetDirconfig.getSearchBaseDn()); int scope = SearchControls.ONELEVEL_SCOPE; String scopePart = ldapUrl.getScope(); if (scopePart != null && scopePart.toLowerCase().startsWith("sub")) { scope = SearchControls.SUBTREE_SCOPE; } if (!linkDn.endsWith(directoryDn) && !directoryDn.endsWith(linkDn)) { // optim #1: if the dns do not match, abort continue; } else if (directoryDn.endsWith(linkDn) && linkDn.length() < directoryDn.length() && scope == SearchControls.ONELEVEL_SCOPE) { // optim #2: the link dn is pointing to elements // that at // upperlevel than directory elements continue; } else { // Search for references elements targetIds.addAll(getReferencedElements(attributes, directoryDn, linkDn, ldapUrl.getFilter(), scope)); } } } finally { rawldapUrls.close(); } } if (dynamicReferences != null && dynamicReferences.length > 0) { // Only the first Dynamic Reference is used LDAPDynamicReferenceDescriptor dynAtt = dynamicReferences[0]; Attribute baseDnsAttribute = attributes.get(dynAtt.baseDN); Attribute filterAttribute = attributes.get(dynAtt.filter); if (baseDnsAttribute != null && filterAttribute != null) { NamingEnumeration<?> baseDns = null; NamingEnumeration<?> filters = null; try { // Get the BaseDN value from the descriptor baseDns = baseDnsAttribute.getAll(); String linkDnValue = baseDns.next().toString(); baseDns.close(); linkDnValue = pseudoNormalizeDn(linkDnValue); // Get the filter value from the descriptor filters = filterAttribute.getAll(); String filterValue = filters.next().toString(); filters.close(); // Get the scope value from the descriptor int scope = "subtree".equalsIgnoreCase(dynAtt.type) ? SearchControls.SUBTREE_SCOPE : SearchControls.ONELEVEL_SCOPE; String directoryDn = pseudoNormalizeDn(targetDirconfig.getSearchBaseDn()); // if the dns match, and if the link dn is pointing to // elements that at upperlevel than directory elements if ((linkDnValue.endsWith(directoryDn) || directoryDn.endsWith(linkDnValue)) && !(directoryDn.endsWith(linkDnValue) && linkDnValue.length() < directoryDn.length() && scope == SearchControls.ONELEVEL_SCOPE)) { // Correct the filter expression filterValue = FilterExpressionCorrector.correctFilter(filterValue, FilterJobs.CORRECT_NOT); // Search for references elements targetIds.addAll(getReferencedElements(attributes, directoryDn, linkDnValue, filterValue, scope)); } } finally { if (baseDns != null) { baseDns.close(); } if (filters != null) { filters.close(); } } } } // return merged attributes return new ArrayList<String>(targetIds); } catch (NamingException e) { throw new DirectoryException("error computing LDAP references", e); } }
From source file:org.wso2.carbon.user.core.ldap.ReadWriteLDAPUserStoreManager.java
@Override public void doUpdateCredentialByAdmin(String userName, Object newCredential) throws UserStoreException { DirContext dirContext = this.connectionSource.getContext(); DirContext subDirContext = null; // first search the existing user entry. String searchBase = realmConfig.getUserStoreProperty(LDAPConstants.USER_SEARCH_BASE); String searchFilter = realmConfig.getUserStoreProperty(LDAPConstants.USER_NAME_SEARCH_FILTER); searchFilter = searchFilter.replace("?", escapeSpecialCharactersForFilter(userName)); SearchControls searchControls = new SearchControls(); searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); searchControls.setReturningAttributes(new String[] { "userPassword" }); NamingEnumeration<SearchResult> namingEnumeration = null; NamingEnumeration passwords = null; try {/*from w w w . java 2 s .c o m*/ namingEnumeration = dirContext.search(escapeDNForSearch(searchBase), searchFilter, searchControls); // here we assume only one user // TODO: what to do if there are more than one user // there can be only only on user SearchResult searchResult = null; while (namingEnumeration.hasMore()) { searchResult = namingEnumeration.next(); String passwordHashMethod = realmConfig.getUserStoreProperty(PASSWORD_HASH_METHOD); if (!UserCoreConstants.RealmConfig.PASSWORD_HASH_METHOD_PLAIN_TEXT .equalsIgnoreCase(passwordHashMethod)) { Attributes attributes = searchResult.getAttributes(); Attribute userPassword = attributes.get("userPassword"); // When admin changes other user passwords he do not have to // provide the old password. Here it is only possible to have one password, if there // are more every one should match with the given old password passwords = userPassword.getAll(); if (passwords.hasMore()) { byte[] byteArray = (byte[]) passwords.next(); String password = new String(byteArray); if (password.startsWith("{")) { passwordHashMethod = password.substring(password.indexOf('{') + 1, password.indexOf('}')); } } } String dnName = searchResult.getName(); subDirContext = (DirContext) dirContext.lookup(searchBase); Attribute passwordAttribute = new BasicAttribute("userPassword"); passwordAttribute.add( UserCoreUtil.getPasswordToStore((String) newCredential, passwordHashMethod, kdcEnabled)); BasicAttributes basicAttributes = new BasicAttributes(true); basicAttributes.put(passwordAttribute); subDirContext.modifyAttributes(dnName, DirContext.REPLACE_ATTRIBUTE, basicAttributes); } // we check whether both carbon admin entry and ldap connection // entry are the same if (searchResult.getNameInNamespace() .equals(realmConfig.getUserStoreProperty(LDAPConstants.CONNECTION_NAME))) { this.connectionSource.updateCredential((String) newCredential); } } catch (NamingException e) { String errorMessage = "Can not access the directory service for user : " + userName; if (log.isDebugEnabled()) { log.debug(errorMessage, e); } throw new UserStoreException(errorMessage, e); } finally { JNDIUtil.closeNamingEnumeration(passwords); JNDIUtil.closeNamingEnumeration(namingEnumeration); JNDIUtil.closeContext(subDirContext); JNDIUtil.closeContext(dirContext); } }
From source file:no.feide.moria.directory.backend.JNDIBackend.java
/** * Retrieves a list of attributes from an element. * @param ldap/*from w w w . ja va2 s.com*/ * A prepared LDAP context. Cannot be <code>null</code>. * @param rdn * The relative DN (to the DN in the LDAP context * <code>ldap</code>). Cannot be <code>null</code>. * @param attributes * The requested attribute's names. Also indirectly referenced * attributes on the form * <code>someReferenceAttribute:someIndirectAttribute</code>, * where the DN in the reference attribute * <code>someReferenceAttribute</code> is followed to look up * <code>someIndirectAttribute</code> from another element. * @return The requested attributes (<code>String</code> names and * <code>String[]</code> values), if they did exist in the * external backend. Otherwise returns those attributes that could * actually be read, this may be an empty <code>HashMap</code>. * Returns an empty <code>HashMap</code> if * <code>attributes</code> is <code>null</code> or an empty * array. Note that attribute values are mapped to * <code>String</code> using ISO-8859-1. * @throws BackendException * If unable to read the attributes from the backend. * @throws NullPointerException * If <code>ldap</code> or <code>rdn</code> is * <code>null</code>. * @see javax.naming.directory.InitialDirContext#getAttributes(java.lang.String, * java.lang.String[]) */ private HashMap<String, String[]> getAttributes(final InitialLdapContext ldap, final String rdn, final String[] attributes) throws BackendException { // Sanity checks. if (ldap == null) throw new NullPointerException("LDAP context cannot be NULL"); if (rdn == null) throw new NullPointerException("RDN cannot be NULL"); if ((attributes == null) || (attributes.length == 0)) return new HashMap<String, String[]>(); // Used to remember attributes to be read through references later on. Hashtable<String, Vector> attributeReferences = new Hashtable<String, Vector>(); // Strip down request, resolving references and removing duplicates. Vector<String> strippedAttributeRequest = new Vector<String>(); for (int i = 0; i < attributes.length; i++) { int indexOfSplitCharacter = attributes[i] .indexOf(DirectoryManagerBackend.ATTRIBUTE_REFERENCE_SEPARATOR); if (indexOfSplitCharacter == -1) { // A regular attribute request. if (!strippedAttributeRequest.contains(attributes[i])) strippedAttributeRequest.add(attributes[i]); } else { // A referenced attribute request. final String referencingAttribute = attributes[i].substring(0, indexOfSplitCharacter); if (!strippedAttributeRequest.contains(referencingAttribute)) strippedAttributeRequest.add(referencingAttribute); // Add to list of attributes to be read through each reference. if (!attributeReferences.containsKey(referencingAttribute)) { // Add new reference. Vector<String> referencedAttribute = new Vector<String>(); referencedAttribute.add(attributes[i].substring(indexOfSplitCharacter + 1)); attributeReferences.put(referencingAttribute, referencedAttribute); } else { // Update existing reference. Vector<String> referencedAttribute = attributeReferences.get(referencingAttribute); if (!referencedAttribute.contains(attributes[i].substring(indexOfSplitCharacter + 1))) referencedAttribute.add(attributes[i].substring(indexOfSplitCharacter + 1)); } } } // The context provider URL and DN, for later logging. String url = "unknown backend"; String dn = "unknown dn"; // Get the attributes from an already initialized LDAP connection. Attributes rawAttributes = null; try { // Remember the URL and bind DN, for later logging. final Hashtable environment = ldap.getEnvironment(); url = (String) environment.get(Context.PROVIDER_URL); dn = (String) environment.get(Context.SECURITY_PRINCIPAL); // Get the attributes. rawAttributes = ldap.getAttributes(rdn, strippedAttributeRequest.toArray(new String[] {})); } catch (NameNotFoundException e) { // Successful authentication but missing user element; no attributes // returned and the event is logged. log.logWarn("No LDAP element found (DN was '" + dn + "')", mySessionTicket); rawAttributes = new BasicAttributes(); } catch (NamingException e) { String a = new String(); for (int i = 0; i < attributes.length; i++) a = a + attributes[i] + ", "; throw new BackendException("Unable to read attribute(s) '" + a.substring(0, a.length() - 2) + "' from '" + rdn + "' on '" + url + "'", e); } // Translate retrieved attributes from Attributes to HashMap. HashMap<String, String[]> convertedAttributes = new HashMap<String, String[]>(); for (int i = 0; i < attributes.length; i++) { // Did we get any attribute back at all? final String requestedAttribute = attributes[i]; Attribute rawAttribute = rawAttributes.get(requestedAttribute); if (rawAttribute == null) { // Attribute was not returned. log.logDebug("Requested attribute '" + requestedAttribute + "' not found on '" + url + "'", mySessionTicket); } else { // Map the attribute values to String[]. ArrayList<String> convertedAttributeValues = new ArrayList<String>(rawAttribute.size()); for (int j = 0; j < rawAttribute.size(); j++) { try { // We either have a String or a byte[]. String convertedAttributeValue = null; try { // Encode String. convertedAttributeValue = new String(((String) rawAttribute.get(j)).getBytes(), DirectoryManagerBackend.ATTRIBUTE_VALUE_CHARSET); } catch (ClassCastException e) { // Encode byte[] to String. convertedAttributeValue = new String(Base64.encodeBase64((byte[]) rawAttribute.get(j)), DirectoryManagerBackend.ATTRIBUTE_VALUE_CHARSET); } convertedAttributeValues.add(convertedAttributeValue); } catch (NamingException e) { throw new BackendException("Unable to read attribute value of '" + rawAttribute.getID() + "' from '" + url + "'", e); } catch (UnsupportedEncodingException e) { throw new BackendException( "Unable to use " + DirectoryManagerBackend.ATTRIBUTE_VALUE_CHARSET + " encoding", e); } } convertedAttributes.put(requestedAttribute, convertedAttributeValues.toArray(new String[] {})); } } // Follow references to look up any indirectly referenced attributes. Enumeration<String> keys = attributeReferences.keys(); while (keys.hasMoreElements()) { // Do we have a reference? final String referencingAttribute = keys.nextElement(); final String[] referencingValues = convertedAttributes.get(referencingAttribute); if (referencingValues == null) { // No reference was found in this attribute. log.logDebug("Found no DN references in attribute '" + referencingAttribute + "'", mySessionTicket); } else { // One (or more) references was found in this attribute. if (referencingValues.length > 1) log.logDebug("Found " + referencingValues.length + " DN references in attribute '" + referencingAttribute + "'; ignoring all but first", mySessionTicket); log.logDebug("Following reference '" + referencingValues[0] + "' found in '" + referencingAttribute + "' to look up attribute(s) '" + attributeReferences.get(referencingAttribute).toString(), mySessionTicket); String providerURL = null; // To be used later. try { // Follow the reference. providerURL = (String) ldap.getEnvironment().get(Context.PROVIDER_URL); providerURL = providerURL.substring(0, providerURL.lastIndexOf("/") + 1) + referencingValues[0]; ldap.addToEnvironment(Context.PROVIDER_URL, providerURL); } catch (NamingException e) { throw new BackendException("Unable to update provider URL in LDAP environment", e); } // Add any referenced attributes returned. HashMap additionalAttributes = getAttributes(ldap, providerURL, (String[]) attributeReferences.get(referencingAttribute).toArray(new String[] {})); Iterator i = additionalAttributes.keySet().iterator(); while (i.hasNext()) { String attributeName = (String) i.next(); convertedAttributes.put(referencingAttribute + DirectoryManagerBackend.ATTRIBUTE_REFERENCE_SEPARATOR + attributeName, (String[]) additionalAttributes.get(attributeName)); } } } return convertedAttributes; }
From source file:org.wso2.carbon.identity.agent.onprem.userstore.manager.ldap.LDAPUserStoreManager.java
/** * {@inheritDoc}// www . j a v a2 s .c o m */ @Override public String[] doGetUserListOfRole(String roleName, int maxItemLimit) throws UserStoreException { boolean debug = log.isDebugEnabled(); List<String> userList = new ArrayList<String>(); String[] names = new String[0]; int givenMax = CommonConstants.MAX_USER_ROLE_LIST; int searchTime = CommonConstants.MAX_SEARCH_TIME; try { givenMax = Integer.parseInt(userStoreProperties.get(CommonConstants.PROPERTY_MAX_USER_LIST)); } catch (Exception e) { givenMax = CommonConstants.MAX_USER_ROLE_LIST; } try { searchTime = Integer.parseInt(userStoreProperties.get(CommonConstants.PROPERTY_MAX_SEARCH_TIME)); } catch (Exception e) { searchTime = CommonConstants.MAX_SEARCH_TIME; } if (maxItemLimit <= 0 || maxItemLimit > givenMax) { maxItemLimit = givenMax; } DirContext dirContext = null; NamingEnumeration<SearchResult> answer = null; try { SearchControls searchCtls = new SearchControls(); searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE); searchCtls.setTimeLimit(searchTime); searchCtls.setCountLimit(maxItemLimit); String searchFilter = userStoreProperties.get(LDAPConstants.GROUP_NAME_LIST_FILTER); String roleNameProperty = userStoreProperties.get(LDAPConstants.GROUP_NAME_ATTRIBUTE); searchFilter = "(&" + searchFilter + "(" + roleNameProperty + "=" + escapeSpecialCharactersForFilter(roleName) + "))"; String membershipProperty = userStoreProperties.get(LDAPConstants.MEMBERSHIP_ATTRIBUTE); String returnedAtts[] = { membershipProperty }; searchCtls.setReturningAttributes(returnedAtts); List<String> userDNList = new ArrayList<String>(); SearchResult sr = null; dirContext = connectionSource.getContext(); // handling multiple search bases String searchBases = userStoreProperties.get(LDAPConstants.GROUP_SEARCH_BASE); String[] roleSearchBaseArray = searchBases.split("#"); for (String searchBase : roleSearchBaseArray) { if (debug) { log.debug("Searching role: " + roleName + " SearchBase: " + searchBase + " SearchFilter: " + searchFilter); } try { // read the DN of users who are members of the group answer = dirContext.search(escapeDNForSearch(searchBase), searchFilter, searchCtls); int count = 0; if (answer.hasMore()) { // to check if there is a result while (answer.hasMore()) { // to check if there are more than one group if (count > 0) { throw new UserStoreException("More than one group exist with name"); } sr = answer.next(); count++; } break; } } catch (NamingException e) { // ignore if (log.isDebugEnabled()) { log.debug(e); } } } if (debug) { log.debug("Found role: " + sr.getNameInNamespace()); } // read the member attribute and get DNs of the users Attributes attributes = sr.getAttributes(); if (attributes != null) { NamingEnumeration attributeEntry = null; for (attributeEntry = attributes.getAll(); attributeEntry.hasMore();) { Attribute valAttribute = (Attribute) attributeEntry.next(); if (membershipProperty.equals(valAttribute.getID())) { NamingEnumeration values = null; for (values = valAttribute.getAll(); values.hasMore();) { String value = values.next().toString(); if (userDNList.size() >= maxItemLimit) { break; } userDNList.add(value); if (debug) { log.debug("Found attribute: " + membershipProperty + " value: " + value); } } } } } if (MEMBER_UID.equals(userStoreProperties.get(LDAPConstants.MEMBERSHIP_ATTRIBUTE))) { /* when the GroupEntryObjectClass is posixGroup, membership attribute is memberUid. We have to retrieve the DN using the memberUid. This procedure has to make an extra call to ldap. alternatively this can be done with a single ldap search using the memberUid and retrieving the display name and username. */ List<String> userDNListNew = new ArrayList<>(); for (String user : userDNList) { String userDN = getNameInSpaceForUserName(user); userDNListNew.add(userDN); } userDNList = userDNListNew; } // iterate over users' DN list and get userName and display name // attribute values String userNameProperty = userStoreProperties.get(LDAPConstants.USER_NAME_ATTRIBUTE); String displayNameAttribute = userStoreProperties.get(LDAPConstants.DISPLAY_NAME_ATTRIBUTE); String[] returnedAttributes = { userNameProperty, displayNameAttribute }; for (String user : userDNList) { if (debug) { log.debug("Getting name attributes of: " + user); } Attributes userAttributes; try { // '\' and '"' characters need another level of escaping before searching userAttributes = dirContext.getAttributes(escapeDNForSearch(user), returnedAttributes); String displayName = null; String userName = null; if (userAttributes != null) { Attribute userNameAttribute = userAttributes.get(userNameProperty); if (userNameAttribute != null) { userName = (String) userNameAttribute.get(); if (debug) { log.debug("UserName: " + userName); } } if (org.apache.commons.lang.StringUtils.isNotEmpty(displayNameAttribute)) { Attribute displayAttribute = userAttributes.get(displayNameAttribute); if (displayAttribute != null) { displayName = (String) displayAttribute.get(); } if (debug) { log.debug("DisplayName: " + displayName); } } } // Username will be null in the special case where the // username attribute has changed to another // and having different userNameProperty than the current // user-mgt.xml if (userName != null) { user = UserStoreUtils.getCombinedName(userName, displayName); userList.add(user); if (debug) { log.debug(user + " is added to the result list"); } } else { if (log.isDebugEnabled()) { log.debug( "User " + user + " doesn't have the user name property : " + userNameProperty); } } } catch (NamingException e) { if (log.isDebugEnabled()) { log.debug("Error in reading user information in the user store for the user " + user + e.getMessage(), e); } } } names = userList.toArray(new String[userList.size()]); } catch (PartialResultException e) { // can be due to referrals in AD. so just ignore error String errorMessage = "Error in reading user information in the user store"; if (isIgnorePartialResultException()) { if (log.isDebugEnabled()) { log.debug(errorMessage, e); } } else { throw new UserStoreException(errorMessage, e); } } catch (NamingException e) { String errorMessage = "Error in reading user information in the user store"; if (log.isDebugEnabled()) { log.debug(errorMessage, e); } throw new UserStoreException(errorMessage, e); } finally { JNDIUtil.closeNamingEnumeration(answer); JNDIUtil.closeContext(dirContext); } return names; }