protected Set<Entry> resolveNestedRoles( final Tuple<String, Dn> role, final LdapConnection ldapConnection, final String roleName) throws AuthException, LdapException { EntryCursor rolesResult = null; EntryCursor _result = null; try { final Set<Entry> result = new HashSet<Entry>(); Dn roleDn = null; final boolean isRoleStringValidDn = Dn.isValid(role.v1()); if (role.v2() != null) { roleDn = role.v2(); } else { // lookup role if (isRoleStringValidDn) { roleDn = ldapConnection.lookup(role.v1()).getDn(); } else { try { // search _result = ldapConnection.search( settings.get( ConfigConstants.ARMOR_AUTHENTICATION_AUTHORIZATION_LDAP_ROLEBASE, ""), settings .get( ConfigConstants.ARMOR_AUTHENTICATION_AUTHORIZATION_LDAP_ROLESEARCH, "(member={0})") .replace("{1}", role.v1()), SearchScope.SUBTREE); // one if (!_result.next()) { log.warn("Cannot resolve role '{}' (NOT FOUND)", role.v1()); } else { // final Entry entry = _result.get(); roleDn = entry.getDn(); if (_result.next()) { log.warn("Cannot resolve role '{}' (MORE THAN ONE FOUND)", role.v1()); } } } catch (final CursorException e) { log.warn("Cannot resolve role '{}' (EXCEPTION: {})", e, role.v1(), e.toString()); } finally { if (_result != null) { _result.close(); } } } } log.trace("role dn resolved to {}", roleDn); rolesResult = ldapConnection.search( settings.get(ConfigConstants.ARMOR_AUTHENTICATION_AUTHORIZATION_LDAP_ROLEBASE, ""), settings .get( ConfigConstants.ARMOR_AUTHENTICATION_AUTHORIZATION_LDAP_ROLESEARCH, "(member={0})") .replace("{0}", roleDn == null ? role.v1() : roleDn.toString()) .replace("{1}", role.v1()), SearchScope.SUBTREE); for (final Iterator iterator = rolesResult.iterator(); iterator.hasNext(); ) { final Entry searchResultEntry = (Entry) iterator.next(); final String _role = searchResultEntry.get(roleName).getString(); log.trace("nested l1 {}", searchResultEntry.getDn()); final Set<Entry> in = resolveNestedRoles( new Tuple<String, Dn>(_role, searchResultEntry.getDn()), ldapConnection, roleName); for (final Iterator<Entry> iterator2 = in.iterator(); iterator2.hasNext(); ) { final Entry entry = iterator2.next(); result.add(entry); log.trace("nested l2 {}", entry.getDn()); } result.add(searchResultEntry); } return result; } finally { if (rolesResult != null) { rolesResult.close(); } } }
/** * adds mandatory operational attributes {@link #MANDATORY_ENTRY_ATOP_MAP} and updates all the * LDIF files. WARN: this method is only called for the first time when schema and config files * are bootstrapped afterwards it is the responsibility of the user to ensure correctness of LDIF * files if modified by hand * * <p>Note: we do these modifications explicitly cause we have no idea if each entry's LDIF file * has the correct values for all these mandatory attributes * * @param partition instance of the partition Note: should only be those which are loaded before * starting the DirectoryService * @param dirService the DirectoryService instance * @throws Exception */ public void updateMandatoryOpAttributes(Partition partition, DirectoryService dirService) throws Exception { CoreSession session = dirService.getAdminSession(); String adminDn = session.getEffectivePrincipal().getName(); ExprNode filter = new PresenceNode(SchemaConstants.OBJECT_CLASS_AT); AttributeType uuidAtT = schemaManager.lookupAttributeTypeRegistry(SchemaConstants.ENTRY_UUID_AT); AttributeType atTypeT = schemaManager.lookupAttributeTypeRegistry(SchemaConstants.ENTRY_CSN_AT); AttributeType creatorAtT = schemaManager.lookupAttributeTypeRegistry(SchemaConstants.CREATORS_NAME_AT); AttributeType createdTimeAtT = schemaManager.lookupAttributeTypeRegistry(SchemaConstants.CREATE_TIMESTAMP_AT); // HashSet<AttributeTypeOptions> options = new HashSet<AttributeTypeOptions>( // MANDATORY_ENTRY_ATOP_MAP.values()); /* AttributeType at; at // String id = SchemaUtils.stripOptions( returnAttribute ); Set<String> options = SchemaUtils.getOptions( returnAttribute ); AttributeType attributeType = session.getDirectoryService() .getSchemaManager().lookupAttributeTypeRegistry( id ); AttributeTypeOptions attrOptions = new AttributeTypeOptions( attributeType, options ); // EntryFilteringCursor cursor = session.search( partition.getSuffixDn(), SearchScope.SUBTREE, filter, AliasDerefMode.NEVER_DEREF_ALIASES, new HashSet<AttributeTypeOptions>( MANDATORY_ENTRY_ATOP_MAP.values() ) ); cursor.beforeFirst(); */ EntryFilteringCursor cursor = session.search( partition.getSuffixDn(), SearchScope.SUBTREE, filter, AliasDerefMode.NEVER_DEREF_ALIASES, SchemaConstants.OBJECT_CLASS_AT_OID, SchemaConstants.ENTRY_UUID_AT_OID, SchemaConstants.ENTRY_CSN_AT_OID, SchemaConstants.CREATORS_NAME_AT_OID, SchemaConstants.CREATORS_NAME_AT_OID); cursor.beforeFirst(); List<Modification> mods = new ArrayList<Modification>(); while (cursor.next()) { Entry entry = cursor.get(); Attribute uuidAt = entry.get(uuidAtT); String uuid = (uuidAt == null ? null : uuidAt.getString()); if (!uuidChecker.isValidSyntax(uuid)) { uuidAt = new DefaultAttribute(uuidAtT, UUID.randomUUID().toString()); } Modification uuidMod = new DefaultModification(ModificationOperation.REPLACE_ATTRIBUTE, uuidAt); mods.add(uuidMod); Attribute csnAt = entry.get(atTypeT); String csn = (csnAt == null ? null : csnAt.getString()); if (!csnChecker.isValidSyntax(csn)) { csnAt = new DefaultAttribute(atTypeT, dirService.getCSN().toString()); } Modification csnMod = new DefaultModification(ModificationOperation.REPLACE_ATTRIBUTE, csnAt); mods.add(csnMod); Attribute creatorAt = entry.get(creatorAtT); String creator = (creatorAt == null ? "" : creatorAt.getString().trim()); if ((creator.length() == 0) || (!Dn.isValid(creator))) { creatorAt = new DefaultAttribute(creatorAtT, adminDn); } Modification creatorMod = new DefaultModification(ModificationOperation.REPLACE_ATTRIBUTE, creatorAt); mods.add(creatorMod); Attribute createdTimeAt = entry.get(createdTimeAtT); String createdTime = (createdTimeAt == null ? null : createdTimeAt.getString()); if (!timeChecker.isValidSyntax(createdTime)) { createdTimeAt = new DefaultAttribute(createdTimeAtT, DateUtils.getGeneralizedTime()); } Modification createdMod = new DefaultModification(ModificationOperation.REPLACE_ATTRIBUTE, createdTimeAt); mods.add(createdMod); if (!mods.isEmpty()) { LOG.debug( "modifying the entry {} after adding missing manadatory operational attributes", entry.getDn()); ModifyOperationContext modifyContext = new ModifyOperationContext(session); modifyContext.setEntry(entry); modifyContext.setDn(entry.getDn()); modifyContext.setModItems(mods); partition.modify(modifyContext); } mods.clear(); } cursor.close(); }
@Override public void fillRoles(final User user, final AuthCredentials optionalAuthCreds) throws AuthException { final String authenticatedUser = user.getName(); if (optionalAuthCreds != null) { optionalAuthCreds.clear(); } Entry entry = null; String dn = null; EntryCursor result = null; EntryCursor rolesResult = null; LdapConnection ldapConnection = null; try { ldapConnection = getConnection(settings); final String bindDn = settings.get(ConfigConstants.ARMOR_AUTHENTICATION_LDAP_BIND_DN, null); if (bindDn != null) { ldapConnection.bind( bindDn, settings.get(ConfigConstants.ARMOR_AUTHENTICATION_LDAP_PASSWORD, null)); } else { ldapConnection.anonymousBind(); } if (Dn.isValid(authenticatedUser)) { // assume dn log.trace("{} is a valid DN", authenticatedUser); entry = ldapConnection.lookup(authenticatedUser); if (entry == null) { throw new AuthException("No user '" + authenticatedUser + "' found"); } } else { // TODO FUTURE all ldap searches: follow referrals result = ldapConnection.search( settings.get(ConfigConstants.ARMOR_AUTHENTICATION_LDAP_USERBASE, ""), settings .get( ConfigConstants.ARMOR_AUTHENTICATION_LDAP_USERSEARCH, "(sAMAccountName={0})") .replace("{0}", authenticatedUser), SearchScope.SUBTREE); if (!result.next()) { throw new AuthException("No user '" + authenticatedUser + "' found"); } entry = result.get(); if (result.next()) { throw new AuthException("More than user found"); } } dn = entry.getDn().toString(); log.trace("User found with DN {}", dn); final Set<String> userRolesDn = new HashSet<String>(); // Roles as an attribute of the user entry // Role names may also be held as the values of an attribute in the user's directory entry. // Use userRoleName to specify the name of this attribute. final String userRoleName = settings.get( ConfigConstants.ARMOR_AUTHENTICATION_AUTHORIZATION_LDAP_USERROLENAME, "memberOf"); if (entry.get(userRoleName) != null) { final Value[] userRoles = Iterators.toArray(entry.get(userRoleName).iterator(), Value.class); for (int i = 0; i < userRoles.length; i++) { final Value value = userRoles[i]; final String possibleRoleDN = value.getString(); if (Dn.isValid(possibleRoleDN)) { userRolesDn.add(possibleRoleDN); } } log.trace("User roles count: {}", userRolesDn.size()); } final Map<Tuple<String, Dn>, Entry> roles = new HashMap<Tuple<String, Dn>, Entry>(); final String roleName = settings.get(ConfigConstants.ARMOR_AUTHENTICATION_AUTHORIZATION_LDAP_ROLENAME, "name"); // replace {2} final String userRoleAttribute = settings.get( ConfigConstants.ARMOR_AUTHENTICATION_AUTHORIZATION_LDAP_USERROLEATTRIBUTE, null); String userRoleAttributeValue = null; if (userRoleAttribute != null) { userRoleAttributeValue = entry.get(userRoleAttribute) == null ? null : entry.get(userRoleAttribute).getString(); } rolesResult = ldapConnection.search( settings.get(ConfigConstants.ARMOR_AUTHENTICATION_AUTHORIZATION_LDAP_ROLEBASE, ""), settings .get( ConfigConstants.ARMOR_AUTHENTICATION_AUTHORIZATION_LDAP_ROLESEARCH, "(member={0})") .replace("{0}", dn) .replace("{1}", authenticatedUser) .replace("{2}", userRoleAttributeValue == null ? "{2}" : userRoleAttributeValue), SearchScope.SUBTREE); for (final Iterator iterator = rolesResult.iterator(); iterator.hasNext(); ) { final Entry searchResultEntry = (Entry) iterator.next(); roles.put( new Tuple<String, Dn>(searchResultEntry.getDn().toString(), searchResultEntry.getDn()), searchResultEntry); } log.trace("non user roles count: {}", roles.size()); for (final Iterator<String> it = userRolesDn.iterator(); it.hasNext(); ) { final String stringVal = it.next(); // lookup final Entry userRole = ldapConnection.lookup(stringVal); roles.put(new Tuple<String, Dn>(stringVal, null), userRole); } // nested roles if (settings.getAsBoolean( ConfigConstants.ARMOR_AUTHENTICATION_AUTHORIZATION_LDAP_RESOLVE_NESTED_ROLES, false)) { log.trace("Evaluate nested roles"); final Set<Entry> nestedReturn = new HashSet<Entry>(roles.values()); for (final Iterator<java.util.Map.Entry<Tuple<String, Dn>, Entry>> iterator = roles.entrySet().iterator(); iterator.hasNext(); ) { final java.util.Map.Entry<Tuple<String, Dn>, Entry> _entry = iterator.next(); final Set<Entry> x = resolveNestedRoles(_entry.getKey(), ldapConnection, roleName); log.trace("{}. nested roles for {} {}", x.size(), _entry.getKey(), roleName); nestedReturn.addAll(x); } for (final Iterator iterator = nestedReturn.iterator(); iterator.hasNext(); ) { final Entry entry2 = (Entry) iterator.next(); final String role = entry2.get(roleName).getString(); user.addRole(role); } if (user instanceof LdapUser) { ((LdapUser) user).addRoleEntries(nestedReturn); } } else { for (final Iterator iterator = roles.values().iterator(); iterator.hasNext(); ) { final Entry entry2 = (Entry) iterator.next(); final String role = entry2.get(roleName).getString(); user.addRole(role); } if (user instanceof LdapUser) { ((LdapUser) user).addRoleEntries(roles.values()); } } } catch (final Exception e) { log.error(e.toString(), e); throw new AuthException(e); } finally { if (result != null) { result.close(); } if (rolesResult != null) { rolesResult.close(); } SecurityUtil.unbindAndCloseSilently(ldapConnection); } }