summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNils Schwabe2014-04-30 15:54:59 +0200
committerNils Schwabe2014-04-30 15:54:59 +0200
commit0ee8c7190cb020101f7807a2f12b26a3f62a89b0 (patch)
treed8f98466325c4d21cbad960b65b2e70b5e047da5
parentAdd some new exceptions for problems with image's data (diff)
downloadmasterserver-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--.gitignore1
-rw-r--r--config/global.properties.example35
-rw-r--r--src/main/java/org/openslx/imagemaster/Globals.java17
-rw-r--r--src/main/java/org/openslx/imagemaster/db/LdapUser.java172
4 files changed, 122 insertions, 103 deletions
diff --git a/.gitignore b/.gitignore
index e31a5ff..44b3383 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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;
}
}