private Entry lookupUser(String username) throws LdapException { StringBuilder userQuery = new StringBuilder(); userQuery.append("(&(objectclass=user)(|"); boolean hasCondition = false; for (String lookupAttr : lookupAttrs) { String attrName = lookupAttr.trim(); if (!attrName.isEmpty()) { userQuery.append('(').append(attrName).append('=').append(username).append(')'); hasCondition = true; } } userQuery.append("))"); if (!hasCondition) { return null; } logger.debug("LDAP user query " + userQuery.toString()); EntryCursor responseCursor = connection.search(userDn, userQuery.toString(), SearchScope.SUBTREE); try { try { if (responseCursor != null && responseCursor.next()) { Entry match = responseCursor.get(); logger.debug("LDAP user query result: " + match.getDn()); return match; } } catch (CursorException e) { logger.debug("LDAP search error", e); return null; } } finally { responseCursor.close(); } return null; }
@Override public User authenticate(final AuthCredentials authCreds) throws AuthException { LdapConnection ldapConnection = null; final String user = authCreds.getUsername(); final char[] password = authCreds.getPassword(); authCreds.clear(); EntryCursor result = null; try { ldapConnection = LDAPAuthorizator.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(); } result = ldapConnection.search( settings.get(ConfigConstants.ARMOR_AUTHENTICATION_LDAP_USERBASE, ""), settings .get(ConfigConstants.ARMOR_AUTHENTICATION_LDAP_USERSEARCH, "(sAMAccountName={0})") .replace("{0}", user), SearchScope.SUBTREE); if (!result.next()) { throw new AuthException("No user " + user + " found"); } final Entry entry = result.get(); final String dn = entry.getDn().toString(); if (result.next()) { throw new AuthException("More than one user found"); } log.trace("Disconnect {}", bindDn == null ? "anonymous" : bindDn); SecurityUtil.unbindAndCloseSilently(ldapConnection); ldapConnection = LDAPAuthorizator.getConnection(settings); log.trace("Try to authenticate dn {}", dn); ldapConnection.bind(dn, new String(password)); final String usernameAttribute = settings.get(ConfigConstants.ARMOR_AUTHENTICATION_LDAP_USERNAME_ATTRIBUTE, null); String username = dn; if (usernameAttribute != null && entry.get(usernameAttribute) != null) { username = entry.get(usernameAttribute).getString(); } log.debug("Authenticated username {}", username); return new LdapUser(username, entry); } catch (final Exception e) { log.error(e.toString(), e); throw new AuthException(e); } finally { if (result != null) { result.close(); } SecurityUtil.unbindAndCloseSilently(ldapConnection); } }
public static LdapConnection getConnection(final Settings settings) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException, LdapException { final boolean useSSL = settings.getAsBoolean(ConfigConstants.ARMOR_AUTHENTICATION_LDAP_LDAPS_SSL_ENABLED, false); final boolean useStartSSL = settings.getAsBoolean( ConfigConstants.ARMOR_AUTHENTICATION_LDAP_LDAPS_STARTTLS_ENABLED, false); final LdapConnectionConfig config = new LdapConnectionConfig(); if (useSSL || useStartSSL) { // ## Truststore ## final KeyStore ts = KeyStore.getInstance( settings.get(ConfigConstants.ARMOR_AUTHENTICATION_LDAP_LDAPS_TRUSTSTORE_TYPE, "JKS")); ts.load( new FileInputStream( new File( settings.get( ConfigConstants.ARMOR_AUTHENTICATION_LDAP_LDAPS_TRUSTSTORE_FILEPATH, null))), settings .get(ConfigConstants.ARMOR_AUTHENTICATION_LDAP_LDAPS_TRUSTSTORE_PASSWORD, "changeit") .toCharArray()); final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(ts); config.setSslProtocol("TLS"); config.setEnabledCipherSuites(SecurityUtil.ENABLED_SSL_CIPHERS); config.setTrustManagers(tmf.getTrustManagers()); } config.setUseSsl(useSSL); config.setUseTls(useStartSSL); config.setTimeout(5000L); // 5 sec final String[] ldapHosts = settings.getAsArray( ConfigConstants.ARMOR_AUTHENTICATION_LDAP_HOST, new String[] {"localhost"}); LdapConnection ldapConnection = null; for (int i = 0; i < ldapHosts.length; i++) { log.trace("Connect to {}", ldapHosts[i]); try { final String[] split = ldapHosts[i].split(":"); config.setLdapHost(split[0]); if (split.length > 1) { config.setLdapPort(Integer.parseInt(split[1])); } else { config.setLdapPort(useSSL ? 636 : 389); } ldapConnection = new LdapNetworkConnection(config); ldapConnection.connect(); if (!ldapConnection.isConnected()) { continue; } else { break; } } catch (final Exception e) { continue; } } if (ldapConnection == null || !ldapConnection.isConnected()) { throw new LdapException( "Unable to connect to any of those ldap servers " + Arrays.toString(ldapHosts)); } return ldapConnection; }
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(); } } }
@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); } }
@Override public void close() throws IOException { connection.close(); }
private Entry getUser(String cn) throws LdapException { return connection.lookup(cn); }