summaryrefslogblamecommitdiffstats
path: root/src/main/java/org/openslx/imagemaster/db/LdapUser.java
blob: 988f43a0234aaa9f8079986af2edbc51c3728406 (plain) (tree)
1
2
3
4
5
6
7
8
9

                                   
                    
                           


                                              
                                               
 
                                         





                                                                   
                                                           

                                                                  
                               
                                                  
                                       
                                            
                                                                


                                                                    
   

                                                                       
                                                                        


                                  
 
                                                                             




                                                                                                                                                                       
         
 

                                               
           
                                                                   
                                                                                              
           

                                                                                                                   
                                                                                                 
                

                                                          
                                                                                                                                       

                                                 
                     

                                                                                 
                                                                
                                                                   

                                                       
                                                              
                                                                   

                                                   
                                                             
                                                                   



                                                                    

                                                                                   









                                                                                                                               
                                                         
                                                                                       

                                                          
                                                       


                                            

                                                                                                                   


                                                    

                                                                                                

                                                                         

                                                                
                                                            
                                                                                         
                                                    

                                                                            

                                                                                                                                                                                           
                         


                                                                                                                                                                      


                                                                                                                                                            
                                                                                             


                                                                                                                      













                                                                                                                                   



                                                    
                                                   
                                                                   
                                                                            

                         
                            
         


                                                                      
                                                               










                                                                                        
                                                                                                                                                 

                                                                                           
 
package org.openslx.imagemaster.db;

import java.io.File;
import java.io.IOException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.cert.CertificateException;

import javax.net.ssl.TrustManagerFactory;

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.LdapConnection;
import org.apache.directory.ldap.client.api.LdapConnectionConfig;
import org.apache.directory.ldap.client.api.LdapNetworkConnection;
import org.apache.log4j.Logger;
import org.apache.mina.filter.ssl.KeyStoreFactory;
import org.openslx.imagemaster.Globals;
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;

/**
 * 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 (DbUser.java).
 */
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 "prefix_username"
	 * @return instance of LDAPUser for matching entry from LDAP or null if sth went wrong
	 */
	public static LdapUser forLogin( final String login, final String password ) throws AuthenticationException
	{
		String username, organization, firstName, lastName, eMail, satelliteAddress = "";
		
		final String[] split = login.split( "_" );
		if (split.length != 2)
			throw new AuthenticationException(AuthenticationError.GENERIC_ERROR, "Login must be in form: prefix_username");
		
		LdapConnection connection = null;
		try {
			LdapConnectionConfig config = new LdapConnectionConfig();

			String ldapHost = Globals.getLdapHost();
			log.debug( "Setting host... " + ldapHost );
			config.setLdapHost( ldapHost );
			
			boolean useSsl = Globals.getLdapSsl();
			log.debug( "Setting use ssl... " + useSsl);
			config.setUseSsl( useSsl );
			
			int ldapPort = Globals.getLdapPort();
			log.debug( "Setting port... " + ldapPort );
			config.setLdapPort( ldapPort );

			// load keystore ...
			KeyStoreFactory ksf = new KeyStoreFactory();
			ksf.setDataFile( new File(Globals.getLdapKeystorePath()) );
			ksf.setPassword( Globals.getLdapKeystorePassword());
			ksf.setType( "jks" );
			
			// ... and set TrustManager
			TrustManagerFactory tmf = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm() );
			tmf.init( ksf.newInstance() );
			
			config.setTrustManagers( tmf.getTrustManagers() );

			connection = new LdapNetworkConnection( config );
		
			log.debug( "Trying to bind..." );
			String bind = Globals.getLdapBindQuery().replace( "%", login );
			connection.bind( bind, password );
			//connection.bind();
			log.debug( "Bind successful" );
			
			
			// make search query
			EntryCursor cursor = connection.search( Globals.getLdapSearchBaseDn(),
					Globals.getLdapSearchFilter().replace( "%", login ), SearchScope.SUBTREE );
			// only use the first result
			cursor.next();
			Entry entry = cursor.get();
			username = entry.get( "cn" ).toString().split( " " )[1].split( "@" )[0];
			organization = entry.get( "cn" ).toString().split( "@" )[1];
			firstName = entry.get( "givenName" ).getString();
			lastName = entry.get( "sn" ).getString();
			eMail = entry.get( "mail" ).getString();
			
			// get the satellite address from db
			DbSatellite dbSatellite = DbSatellite.fromSuffix( organization );
			if ( dbSatellite != null ) {
				satelliteAddress = dbSatellite.getAddress();
			} else {
				// Organization is not known. This should not happen because the login would have failed then.
				throw new AuthenticationException( AuthenticationError.GENERIC_ERROR, "Your Organization is not known by the server. Please contact your administrator." );
			}
			// everything went fine
			return new LdapUser( 0, username, Sha512Crypt.Sha512_crypt( password, null, 0 ), organization, firstName, lastName, eMail, satelliteAddress );
		} catch ( LdapException e) {
			if ( e.getMessage().contains( "Cannot connect on the server" ) ) {
				DbSatellite dbSatellite = DbSatellite.fromPrefix(split[0]);
				if (dbSatellite == null) throw new AuthenticationException(AuthenticationError.INVALID_CREDENTIALS, "Credentials invalid.");
				String lo = split[1] + "@" + dbSatellite.getOrganizationId();
				log.info( "LDAP server could not be reached. Trying to connect locally with: " + lo );
				return LdapUser.localLogin(lo, password);
			}
			e.printStackTrace();
			throw new AuthenticationException( AuthenticationError.GENERIC_ERROR, "Something went wrong." );
		} catch ( CursorException e ) {
			e.printStackTrace();
			throw new AuthenticationException( AuthenticationError.INVALID_CREDENTIALS, "Could not find user entry." );
		} catch ( IOException e ) {
			// could not load keyfile
			e.printStackTrace();
		} catch ( NoSuchAlgorithmException e ) {
			// could not load algorithm
			e.printStackTrace();
		} catch ( KeyStoreException | NoSuchProviderException | CertificateException e ) {
			// some problem with the key
			e.printStackTrace();
		} finally {
			// close connection
			try {
				connection.unBind();
				connection.close();
			} catch ( IOException | LdapException e ) {
				// was not connected so don't do anything...
			}
		}
		return null;
	}

	/**
	 * Login user locally if external Ldap server is not available
	 * @param login Must be in form "username@organization"
	 * @param password The user's password
	 */
	private static LdapUser localLogin( String login, String password )
	{
		DbUser user = DbUser.forLogin( login );
		if (user == null) return null; // no user found
		
		// check users password
		if (!Sha512Crypt.verifyPassword( password, user.password )) return null;
		
		// return ldapuser if valid
		return new LdapUser( user.userId, user.login, Sha512Crypt.Sha512_crypt( password, null, 0 ), user.organizationId, user.firstName,
					user.lastName, user.eMail, user.satelliteAddress );
	}
}