/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.server.auth.password;
import java.util.Map;
import javax.naming.NamingException;
import org.apache.sshd.server.auth.LdapAuthenticator;
import org.apache.sshd.server.session.ServerSession;
/**
* Uses LDAP to authenticate a user and password. By default it can achieve this using 2 ways:
* <OL>
* <P><LI>
* Comparing the provided password with the one stored in LDAP. In this case,
* the bind DN and password patterns can be either empty (if anonymous access
* allowed) or can contain the administrative username / password required to
* run the LDAP query. The search filter pattern should be set to require a
* match for <U>both</U> the username and password - e.g., <code>"(&(user={0})(password={1}))"</code>.
* The set default ({@link #DEFAULT_SEARCH_FILTER_PATTERN}) uses the most
* commonly encountered attributes names for this purpose.
* </LI></P>
*
* <P><LI>
* Using the original username + password to access LDAP - in which case the very
* success of retrieving anything can be considered a successful authentication.
* In this case, the bind DN and password patterns should be set up to generate
* the correct credentials - the default is to "echo" the provided
* username and password as-is. E.g., if the username is always the alias part
* of a known e-mail, the bind DN should be set to <code>"{0}@my.domain.com"</code>.
* </LI></P>
* </OL>
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class LdapPasswordAuthenticator extends LdapAuthenticator implements PasswordAuthenticator {
public static final String DEFAULT_PASSWORD_ATTR_NAME = "userPassword";
public static final String DEFAULT_SEARCH_FILTER_PATTERN =
"(&(" + DEFAULT_USERNAME_ATTR_NAME + "={0})(" + DEFAULT_PASSWORD_ATTR_NAME + "={1}))";
public LdapPasswordAuthenticator() {
setRetrievedAttributes(null);
setSearchFilterPattern(DEFAULT_SEARCH_FILTER_PATTERN);
}
@Override
public boolean authenticate(String username, String password, ServerSession session) throws PasswordChangeRequiredException {
try {
Map<String, ?> attrs = resolveAttributes(username, password, session);
return authenticate(username, password, session, attrs);
} catch (NamingException | RuntimeException e) {
log.warn("authenticate({}@{}) failed ({}) to query: {}",
username, session, e.getClass().getSimpleName(), e.getMessage());
if (log.isDebugEnabled()) {
log.debug("authenticate(" + username + "@" + session + ") query failure details", e);
}
return false;
}
}
protected boolean authenticate(String username, String password, ServerSession session, Map<String, ?> attrs) {
/*
* By default we assume that the user + password are the same for
* accessing the LDAP as the user's account, so the very LDAP query
* success is enough
*/
return true;
}
}