diff options
author | Nils Schwabe | 2014-04-30 15:54:59 +0200 |
---|---|---|
committer | Nils Schwabe | 2014-04-30 15:54:59 +0200 |
commit | 0ee8c7190cb020101f7807a2f12b26a3f62a89b0 (patch) | |
tree | d8f98466325c4d21cbad960b65b2e70b5e047da5 | |
parent | Add some new exceptions for problems with image's data (diff) | |
download | masterserver-0ee8c7190cb020101f7807a2f12b26a3f62a89b0.tar.gz masterserver-0ee8c7190cb020101f7807a2f12b26a3f62a89b0.tar.xz masterserver-0ee8c7190cb020101f7807a2f12b26a3f62a89b0.zip |
Add connecting to LDAP with cert (JKS in globals.config)
Connecting to BW LDAP works now (finally!!)
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | config/global.properties.example | 35 | ||||
-rw-r--r-- | src/main/java/org/openslx/imagemaster/Globals.java | 17 | ||||
-rw-r--r-- | src/main/java/org/openslx/imagemaster/db/LdapUser.java | 172 |
4 files changed, 122 insertions, 103 deletions
@@ -9,4 +9,5 @@ /gen-java /src/main/properties/ftp.properties /config/keystore.jks +/config/ldap.jks diff --git a/config/global.properties.example b/config/global.properties.example index 0b26f75..668bfdb 100644 --- a/config/global.properties.example +++ b/config/global.properties.example @@ -7,31 +7,31 @@ # the dir where the images are stored image_dir=/tmp -# keystore (.jks format) -keystore=./config/keystore.jks - ##################### -# LDAP data # +# LDAP # ##################### # the port of the LDAP server ldap_port=636 # the host address of the LDAP server -ldap_host=bv1.ruf.uni-freiburg.de +ldap_host=bwservices-test.vm.uni-freiburg.de # SSL usage ldap_ssl=true # bind query (don't forget to escape \= and use a % for the username replacement -ldap_bind_query=uid\=%,ou\=people,dc\=uni-freiburg,dc\=de +ldap_bind_query=uid\=%,ou\=users,dc\=bwlehrpool,dc\=uni-freiburg,dc\=de # search baseDn -ldap_search_base_dn=ou\=people,dc\=uni-freiburg,dc\=de - +ldap_search_base_dn=ou\=users,dc\=bwlehrpool,dc\=uni-freiburg,dc\=de # search filter (use a % for the username replacement -ldap_search_filter=(&(objectclass\=person)(uid\=%)) +ldap_search_filter=(&(objectclass\=person)(|(uid=%)(cn=%))) + +# ldap keystore with public key +ldap_keystore_path=./config/ldap.jks +ldap_keystore_password=changeit ##################### # Session # @@ -53,5 +53,18 @@ ftp_base_dir=/tmp # the port of the ftp server ftp_port=2221 -# timeout for kicking ftp users (in minutes) -ftp_timeout=60
\ No newline at end of file +# timeout for kicking idling ftp users (in minutes) +ftp_timeout=30 + +##################### +# Keystore # +##################### + +# keystore (.jks format) +keystore_file=./config/keystore.jks + +# keystore alias +keystore_alias=ftp + +#keystore password +keystore_password=password
\ No newline at end of file diff --git a/src/main/java/org/openslx/imagemaster/Globals.java b/src/main/java/org/openslx/imagemaster/Globals.java index 166e629..3dedc82 100644 --- a/src/main/java/org/openslx/imagemaster/Globals.java +++ b/src/main/java/org/openslx/imagemaster/Globals.java @@ -22,7 +22,7 @@ public class Globals public static enum PropString { - IMAGEDIR, KEYSTOREFILE, KEYSTOREALIAS, KEYSTOREPASSWORD, LDAPHOST, LDAPBINDQUERY, LDAPSEARCHBASEDN, LDAPSEARCHFILTER, FTPBASEDIR + IMAGEDIR, KEYSTOREFILE, KEYSTOREALIAS, KEYSTOREPASSWORD, LDAPHOST, LDAPBINDQUERY, LDAPSEARCHBASEDN, LDAPSEARCHFILTER, LDAPKEYSTOREPASSWORD, LDAPKEYSTOREPATH, FTPBASEDIR } public static enum PropBool @@ -61,6 +61,10 @@ public class Globals || Globals.getPropertyString( PropString.LDAPSEARCHBASEDN ).isEmpty() || Globals.getPropertyString( PropString.LDAPSEARCHFILTER ) == null || Globals.getPropertyString( PropString.LDAPSEARCHFILTER ).isEmpty() + || Globals.getPropertyString( PropString.LDAPKEYSTOREPASSWORD ) == null + || Globals.getPropertyString( PropString.LDAPKEYSTOREPASSWORD ).isEmpty() + || Globals.getPropertyString( PropString.LDAPKEYSTOREPATH ) == null + || Globals.getPropertyString( PropString.LDAPKEYSTOREPATH ).isEmpty() || Globals.getPropertyString( PropString.FTPBASEDIR ) == null || Globals.getPropertyString( PropString.FTPBASEDIR ).isEmpty() || Globals.getPropertyString( PropString.KEYSTOREFILE ) == null @@ -79,13 +83,13 @@ public class Globals } // check ldap_bind_query - if ( StringUtils.countMatches( Globals.getPropertyString( PropString.LDAPBINDQUERY ), "%" ) != 1 ) { + if ( StringUtils.countMatches( Globals.getPropertyString( PropString.LDAPBINDQUERY ), "%" ) == 0 ) { log.error( "ldap_bind_query does not contain '%'" ); return false; } // check ldap_search_filter - if ( StringUtils.countMatches( Globals.getPropertyString( PropString.LDAPSEARCHFILTER ), "%" ) != 1 ) { + if ( StringUtils.countMatches( Globals.getPropertyString( PropString.LDAPSEARCHFILTER ), "%" ) == 0) { log.error( "ldap_search_filter does not contain '%'" ); return false; } @@ -170,6 +174,12 @@ public class Globals case LDAPSEARCHFILTER: result = properties.getProperty( "ldap_search_filter" ); break; + case LDAPKEYSTOREPASSWORD: + result = properties.getProperty( "ldap_keystore_password" ); + break; + case LDAPKEYSTOREPATH: + result = properties.getProperty( "ldap_keystore_path" ); + break; case FTPBASEDIR: result = properties.getProperty( "ftp_base_dir" ); break; @@ -188,6 +198,7 @@ public class Globals switch ( props ) { case LDAPSSL: result = properties.getProperty( "ldap_ssl" ); + break; default: result = ""; break; diff --git a/src/main/java/org/openslx/imagemaster/db/LdapUser.java b/src/main/java/org/openslx/imagemaster/db/LdapUser.java index deb30f3..a38b805 100644 --- a/src/main/java/org/openslx/imagemaster/db/LdapUser.java +++ b/src/main/java/org/openslx/imagemaster/db/LdapUser.java @@ -1,9 +1,18 @@ package org.openslx.imagemaster.db; +import java.io.File; import java.io.IOException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; +import javax.net.ssl.KeyManager; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; import org.apache.directory.api.ldap.model.cursor.CursorException; @@ -11,11 +20,14 @@ 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.Globals.PropBool; +import org.openslx.imagemaster.Globals.PropInt; import org.openslx.imagemaster.Globals.PropString; import org.openslx.imagemaster.session.User; import org.openslx.imagemaster.thrift.iface.AuthenticationError; @@ -23,35 +35,6 @@ 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. @@ -71,91 +54,102 @@ public class LdapUser extends User * 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 + * @return instance of LDAPUser for matching entry from LDAP */ public static LdapUser forLogin( final String login, final String password ) throws AuthenticationException { String username, organization, firstName, lastName, eMail, satelliteAddress; - String[] temp = login.split( "@" ); - if ( temp.length != 2 ) - throw new AuthenticationException( AuthenticationError.GENERIC_ERROR, "Login must be in form user@organization.com" ); - - LdapConnectionConfig ldapConfig = new LdapConnectionConfig(); - ldapConfig.setTrustManagers( new MyTrustManager() ); - ldapConfig.setLdapPort( Globals.getPropertyInt( Globals.PropInt.LDAPPORT ) ); - ldapConfig.setLdapHost( Globals.getPropertyString( Globals.PropString.LDAPHOST ) ); - ldapConfig.setUseSsl( Globals.getPropertyBool( PropBool.LDAPSSL ) ); - - LdapNetworkConnection connection = new LdapNetworkConnection( ldapConfig ); - - // bind connection - try { - if ( connection.connect() ) { - String name = Globals.getPropertyString( PropString.LDAPBINDQUERY ).replace( "%", login ).replace( "@", "\\40" ); - log.info( "Bind with: " + name ); - connection.bind( name, 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 +// String[] temp = login.split( "@" ); +// if ( temp.length != 2 ) +// throw new AuthenticationException( AuthenticationError.GENERIC_ERROR, "Login must be in form user@organization.com" ); + + LdapConnection connection = null; try { + LdapConnectionConfig config = new LdapConnectionConfig(); + + // TODO: Load from configuration file + + String ldapHost = Globals.getPropertyString( PropString.LDAPHOST ); + log.info( "Setting host... " + ldapHost ); + config.setLdapHost( ldapHost ); + + boolean useSsl = Globals.getPropertyBool( PropBool.LDAPSSL ); + log.info( "Setting use ssl... " + useSsl); + config.setUseSsl( useSsl ); + + int ldapPort = Globals.getPropertyInt( PropInt.LDAPPORT ); + log.info( "Setting port... " + ldapPort ); + config.setLdapPort( ldapPort ); + + // load keystore ... + KeyStoreFactory ksf = new KeyStoreFactory(); + ksf.setDataFile( new File(Globals.getPropertyString( PropString.LDAPKEYSTOREPATH )) ); + ksf.setPassword( Globals.getPropertyString( PropString.LDAPKEYSTOREPASSWORD ) ); + 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.info( "Trying to bind..." ); + String bind = Globals.getPropertyString( PropString.LDAPBINDQUERY ).replace( "%", login ); + connection.bind( bind, password ); + //connection.bind(); + log.info( "Bind successful" ); + + + // make search query EntryCursor cursor = connection.search( Globals.getPropertyString( Globals.PropString.LDAPSEARCHBASEDN ), Globals.getPropertyString( Globals.PropString.LDAPSEARCHFILTER ).replace( "%", login ), SearchScope.SUBTREE ); // only use the first result cursor.next(); Entry entry = cursor.get(); - username = entry.get( "cn" ).getString(); - organization = "Test Organization"; // will be filled with bwIDM LDAP server + 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( "rufPreferredMail" ).getString(); + eMail = entry.get( "mail" ).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"; + // 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." ); } - } catch ( LdapException | CursorException e1 ) { - return null; + // everything went fine + return new LdapUser( 0, username, Sha512Crypt.Sha512_crypt( password, null, 0 ), organization, firstName, lastName, eMail, satelliteAddress ); + } catch ( LdapException e) { + 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(); - } catch ( LdapException e ) { - return null; - } - try { connection.close(); - } catch ( IOException e ) { - return null; + } catch ( IOException | LdapException e ) { + e.printStackTrace(); + throw new AuthenticationException( AuthenticationError.GENERIC_ERROR, "Something went very wrong." ); } } - return new LdapUser( 0, username, Sha512Crypt.Sha512_crypt( password, null, 0 ), organization, firstName, lastName, eMail, satelliteAddress ); + return null; } } |