package org.ovirt.engine.core.utils.ipa;
import static org.ovirt.engine.core.utils.kerberos.InstallerConstants.ERROR_PREFIX;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import org.ovirt.engine.core.ldap.LdapProviderType;
import org.ovirt.engine.core.ldap.RootDSEData;
import org.ovirt.engine.core.utils.CLIParser;
import org.springframework.ldap.AuthenticationException;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.LdapContextSource;
public class SimpleAuthenticationCheck {
private static String INVALID_CREDENTIALS_ERROR_CODE = "49";
private LdapProviderType ldapProviderType;
public enum Arguments {
domain,
user,
password
}
private void printUsage() {
System.out.println("Usage:");
System.out
.println("SimpleAuthenticationCheck: -domain=<domains> -user=<user> -password=<password>");
}
private String getLdapUrl(String ldapServer) {
return "ldap://" + ldapServer;
}
private boolean validate(CLIParser parser) {
Arguments[] argsToValidate =
{ Arguments.domain, Arguments.user, Arguments.password };
for (Arguments argument : argsToValidate) {
if (!parser.hasArg(argument.name())) {
System.out.println(argument.name() + " is required");
return false;
}
}
return true;
}
public static void main(String[] args) {
SimpleAuthenticationCheck util = new SimpleAuthenticationCheck();
CLIParser parser = new CLIParser(args);
if (!util.validate(parser)) {
util.printUsage();
System.exit(ReturnStatus.INPUT_VALIDATION_FAILURE.ordinal());
}
String username = parser.getArg(Arguments.user.name());
String password = parser.getArg(Arguments.password.name());
String domain = parser.getArg(Arguments.domain.name());
StringBuffer userGuid = new StringBuffer();
ReturnStatus status = util.printUserGuid(domain, username, password, "localhost:389", userGuid);
System.exit(status.ordinal());
}
private ReturnStatus updateProviderType(String ldapServer,
String domain,
String username,
String password) {
try {
RootDSEData rootDSEData = new RootDSEData(getDirContext(getLdapUrl(ldapServer)));
ldapProviderType = rootDSEData.getLdapProviderType();
return ReturnStatus.OK;
} catch (Exception ex) {
System.err.println(ERROR_PREFIX + "Cannot detect LDAP provider type for domain " + domain
+ ", details: " + ex.getMessage());
return ReturnStatus.CANNOT_DETECT_PROVIDER_TYPE;
}
}
public ReturnStatus printUserGuid(String domain,
String username,
String password,
String ldapServerUrl,
StringBuffer userGuid) {
ReturnStatus updateProviderTypeStatus =
updateProviderType(ldapServerUrl, domain, username, password);
if (updateProviderTypeStatus != ReturnStatus.OK) {
return updateProviderTypeStatus;
}
LdapContextSource contextSource = getContextSource(domain, username, password, ldapServerUrl);
try {
contextSource.afterPropertiesSet();
} catch (Exception e) {
System.err.println(ERROR_PREFIX + "Failed setting LDAP context for domain " + domain);
return ReturnStatus.LDAP_CONTEXT_FAILURE;
}
if (updateProviderTypeStatus.equals(ReturnStatus.OK)) {
LdapTemplate ldapTemplate = new LdapTemplate(contextSource);
String query = "";
ContextMapper contextMapper;
if (ldapProviderType.equals(LdapProviderType.ipa)) {
query = "(&(objectClass=posixAccount)(objectClass=krbPrincipalAux)(uid=" + username + "))";
contextMapper = new IPAUserContextMapper();
// AD
} else if (ldapProviderType.equals(LdapProviderType.activeDirectory)) {
contextMapper = new ADUserContextMapper();
// RHDS
} else {
query = "(&(objectClass=person)(uid=" + username + "))";
contextMapper = new RHDSUserContextMapper();
}
try {
List searchResult =
ldapTemplate.search("", query, contextMapper);
if (searchResult == null) {
System.err.println(ERROR_PREFIX + "Cannot query user " + username + " from domain " + domain);
return ReturnStatus.CANNOT_QUERY_USER;
} else {
userGuid.append((String) searchResult.get(0));
System.out.println("User guid is: " + userGuid.toString());
}
} catch (org.springframework.ldap.AuthenticationException authEx) {
return authenticationReturnStatus(authEx, username, domain);
} catch (Exception ex) {
System.err.println(ERROR_PREFIX + "Cannot query user " + username + " from domain " + domain
+ ", details: " + ex.getMessage());
return ReturnStatus.CANNOT_QUERY_USER;
}
return ReturnStatus.OK;
} else {
return updateProviderTypeStatus;
}
}
/***
* Returns the ReturnStatus according to the given AuthenticationException. Either INVALID_CREDENTIALS if this is
* the case, or the general CANNOT_AUTHENTICATE_USER otherwise.
* @param authEx
*/
private ReturnStatus authenticationReturnStatus(AuthenticationException authEx, String userName, String domain) {
ReturnStatus returnStatus = ReturnStatus.CANNOT_AUTHENTICATE_USER;
String authExMessage = authEx.getMessage();
// Using contains() since the AuthenticationException does not have an error code property
if (authExMessage != null && authExMessage.contains(INVALID_CREDENTIALS_ERROR_CODE)) {
System.err.println(ERROR_PREFIX + "Invalid credentials for " + userName + " and domain " + domain
+ ", details: " + authEx.getMessage());
returnStatus = ReturnStatus.INVALID_CREDENTIALS;
} else {
System.err.println(ERROR_PREFIX + "Cannot authenticate user " + userName + " to domain " + domain
+ ", details: " + authEx.getMessage());
}
return returnStatus;
}
private static String domainToDN(String domain) {
String returnValue = "dc=" + domain.replaceAll("\\.", ",dc=");
return returnValue;
}
private LdapContextSource getContextSource(String domain,
String username,
String password,
String ldapServer) {
LdapContextSource context = new LdapContextSource();
String ldapBaseDn = domainToDN(domain);
StringBuilder ldapUserDn = new StringBuilder();
if (ldapProviderType.equals(LdapProviderType.ipa)) {
ldapUserDn.append("uid=").append(username).append(",cn=Users").append(",cn=Accounts,");
} else if (ldapProviderType.equals(LdapProviderType.rhds)) {
ldapUserDn.append("uid=").append(username).append(",ou=People");
} else {
ldapUserDn.append("CN=").append(username).append(",CN=Users,");
}
ldapUserDn.append(ldapBaseDn);
context.setUrl(getLdapUrl(ldapServer));
context.setBase(ldapBaseDn);
context.setUserDn(ldapUserDn.toString());
context.setPassword(password);
context.setReferral("follow");
Map<String, String> baseEnvironmentProperties = new HashMap<String, String>();
// objectGUID - for AD
baseEnvironmentProperties.put("java.naming.ldap.attributes.binary", "objectGUID");
context.setBaseEnvironmentProperties(baseEnvironmentProperties);
return context;
}
private static DirContext getDirContext(String ldapServer) throws NamingException {
Hashtable env = new Hashtable(11);
env.put(Context.SECURITY_AUTHENTICATION, "SIMPLE");
env.put(Context.SECURITY_PRINCIPAL, "");
env.put(Context.SECURITY_CREDENTIALS, "");
env.put(Context.REFERRAL, "follow");
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapServer.toString());
return new InitialDirContext(env);
}
}