package org.openslx.imagemaster.db; import java.io.IOException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.X509TrustManager; import org.apache.directory.api.ldap.model.cursor.CursorException; import org.apache.directory.api.ldap.model.cursor.EntryCursor; import org.apache.directory.api.ldap.model.entry.Entry; import org.apache.directory.api.ldap.model.exception.LdapException; import org.apache.directory.api.ldap.model.message.SearchScope; import org.apache.directory.ldap.client.api.LdapConnectionConfig; import org.apache.directory.ldap.client.api.LdapNetworkConnection; import org.apache.log4j.Logger; import org.openslx.imagemaster.session.User; import org.openslx.imagemaster.thrift.iface.AuthenticationError; import org.openslx.imagemaster.thrift.iface.AuthenticationException; import org.openslx.imagemaster.util.Sha512Crypt; /** * This TrustManager is used to accept custom certificates. * TODO: Once we are talking to the real server(s), we should * actually verify the cert, or we could just stop using ssl * altogether. */ class MyTrustManager implements X509TrustManager { @Override public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {} @Override public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {} @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } } /** * Represents a user instance that was queries (primarily) from LDAP. * Additional information that is not provided by the LDAP server might * be fetched from other sources, like the local database. */ public class LdapUser extends User { private static final Logger log = Logger.getLogger( LdapUser.class ); protected LdapUser(int userId, String username, String password, String organization, String firstName, String lastName, String eMail, String satelliteAddress) { super(userId, username, password, organization, firstName, lastName, eMail, satelliteAddress); } /** * Query LDAP for user with given login * @param login Login of user in the form "user@organization.com" * @return instance of LDAPUser for matching entry from LDAP, or null if not found */ @SuppressWarnings("finally") public static LdapUser forLogin( final String login, final String password ) throws AuthenticationException { String username, organization, firstName, lastName, eMail, satelliteAddress; // TODO: Read connection info from config file LdapConnectionConfig ldapConfig = new LdapConnectionConfig(); ldapConfig.setTrustManagers(new MyTrustManager()); ldapConfig.setLdapPort(636); ldapConfig.setLdapHost("bv1.ruf.uni-freiburg.de"); ldapConfig.setUseSsl(true); LdapNetworkConnection connection = new LdapNetworkConnection( ldapConfig ); // bind connection // TODO: Hard coded stuff here too. binddn, search query etc. need to be configurable try { if ( connection.connect() ) connection.bind("uid=" + login + ",ou=people,dc=uni-freiburg,dc=de", password); } catch (LdapException e1) { log.warn( "Connection to LDAP failed: " + e1.getMessage() ); } if ( !connection.isConnected() ) { try { connection.unBind(); connection.close(); } catch (LdapException | IOException e) { // Not doing anything here, as ldap already failed... } throw new AuthenticationException( AuthenticationError.GENERIC_ERROR, "Could not connect to LDAP server." ); } // test authorization if ( !connection.isAuthenticated() ) { try { connection.unBind(); connection.close(); } catch (LdapException | IOException e) { // Failing disconnect... Can't do much about it, just go on } throw new AuthenticationException( AuthenticationError.INVALID_CREDENTIALS, "Could not authenticate to LDAP server. Invalid credentials?" ); } // make search query try { EntryCursor cursor = connection.search("ou=people,dc=uni-freiburg,dc=de", "(&(objectclass=person)(uid=" + login + "))", SearchScope.SUBTREE); // only use the first result cursor.next(); Entry entry = cursor.get(); username = entry.get("uid").getString(); organization = "Test Organization"; // will be filled with bwIDM LDAP server firstName = entry.get("givenName").getString(); lastName = entry.get("sn").getString(); eMail = entry.get("rufPreferredMail").getString(); // get the satellite address from db DbSatellite dbSatellite = DbSatellite.fromOrganization(organization); if (dbSatellite != null) { satelliteAddress = dbSatellite.getAddress(); } else { // TODO: Organization is not known.. Handle this satelliteAddress = "addressNotKown"; } } catch (LdapException | CursorException e1) { return null; } finally { // close connection try { connection.unBind(); } catch (LdapException e) { return null; } try { connection.close(); } catch (IOException e) { return null; } } return new LdapUser(0, username, Sha512Crypt.Sha512_crypt(password, null, 0), organization, firstName, lastName, eMail, satelliteAddress); } }