From 9af765479c941d3664516ebcb8e203f4331264a9 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Mon, 29 Sep 2014 18:16:52 +0200 Subject: Use KeyPair classes for satellite authentication --- .../java/org/openslx/imagemaster/db/MySQL.java | 1 + .../org/openslx/imagemaster/server/ApiServer.java | 23 ++++---- .../serversession/ServerAuthenticator.java | 68 +++++++++------------- .../thrift/server/ImageServerHandler.java | 2 +- .../org/openslx/imagemaster/util/RandomString.java | 14 +++++ 5 files changed, 56 insertions(+), 52 deletions(-) diff --git a/src/main/java/org/openslx/imagemaster/db/MySQL.java b/src/main/java/org/openslx/imagemaster/db/MySQL.java index 3b5438d..9443879 100644 --- a/src/main/java/org/openslx/imagemaster/db/MySQL.java +++ b/src/main/java/org/openslx/imagemaster/db/MySQL.java @@ -67,6 +67,7 @@ class MySQL ds.setDatabaseName( dbname ); ds.setUser( user ); ds.setPassword( password ); + ds.setEncoding( "UTF-8" ); db = Database.forDataSource( ds ); } catch ( Exception e ) { log.fatal( "Error initializing mysql data source!" ); diff --git a/src/main/java/org/openslx/imagemaster/server/ApiServer.java b/src/main/java/org/openslx/imagemaster/server/ApiServer.java index ce20020..b39a517 100644 --- a/src/main/java/org/openslx/imagemaster/server/ApiServer.java +++ b/src/main/java/org/openslx/imagemaster/server/ApiServer.java @@ -119,15 +119,17 @@ public class ApiServer * key of the requesting satellite server * @throws ServerAuthenticationException when organization is invalid/unknown */ - public static String startServerAuthentication( String organization ) + public static ByteBuffer startServerAuthentication( String organization ) throws ServerAuthenticationException { - if ( organization == null || organization.isEmpty() ) { + if ( organization == null || organization.isEmpty() ) throw new ServerAuthenticationException( ServerAuthenticationError.INVALID_ORGANIZATION, "Empty organization" ); - } - if ( DbSatellite.fromOrganization( organization ) == null ) { - throw new ServerAuthenticationException( ServerAuthenticationError.INVALID_ORGANIZATION, "Unknown organization" ); - } + + DbSatellite satellite = DbSatellite.fromOrganization( organization ); + if ( satellite == null ) + throw new ServerAuthenticationException( ServerAuthenticationError.INVALID_ORGANIZATION, "Unknown organization: '" + organization + "'" ); + if ( satellite.getPubkey() == null ) + throw new ServerAuthenticationException( ServerAuthenticationError.INVALID_KEY, "There is no public key known for your organization." ); return ServerAuthenticator.startServerAuthentication( organization ); } @@ -148,11 +150,12 @@ public class ApiServer throw new ServerAuthenticationException( ServerAuthenticationError.INVALID_ORGANIZATION, "Empty organization or challengeResponse" ); } DbSatellite satellite = DbSatellite.fromOrganization( organization ); - if ( satellite == null ) { + if ( satellite == null ) throw new ServerAuthenticationException( ServerAuthenticationError.INVALID_ORGANIZATION, "Unknown organization" ); - } - final ServerUser serverUser = ServerAuthenticator.serverAuthenticate( - organization, satellite.getAddress(), challengeResponse ); + if ( satellite.getPubkey() == null ) + throw new ServerAuthenticationException( ServerAuthenticationError.INVALID_KEY, "There is no public key known for your organization." ); + + final ServerUser serverUser = ServerAuthenticator.serverAuthenticate( satellite, challengeResponse ); final ServerSession session = new ServerSession( serverUser ); return ServerSessionManager.addSession( session ); diff --git a/src/main/java/org/openslx/imagemaster/serversession/ServerAuthenticator.java b/src/main/java/org/openslx/imagemaster/serversession/ServerAuthenticator.java index 6ef037c..d851c4e 100644 --- a/src/main/java/org/openslx/imagemaster/serversession/ServerAuthenticator.java +++ b/src/main/java/org/openslx/imagemaster/serversession/ServerAuthenticator.java @@ -1,14 +1,15 @@ package org.openslx.imagemaster.serversession; import java.nio.ByteBuffer; -import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.apache.log4j.Logger; import org.apache.thrift.TException; -import org.openslx.imagemaster.thrift.iface.AuthenticationException; +import org.openslx.encryption.AsymEncryptionHandler; +import org.openslx.imagemaster.db.DbSatellite; import org.openslx.imagemaster.thrift.iface.ServerAuthenticationError; import org.openslx.imagemaster.thrift.iface.ServerAuthenticationException; -import org.openslx.imagemaster.util.AsymMessageVerifier; import org.openslx.imagemaster.util.RandomString; /** @@ -18,8 +19,11 @@ public class ServerAuthenticator { private static Logger log = Logger.getLogger( ServerAuthenticator.class ); - // map of currently authenticating servers - private static HashMap authenticatingServers = new HashMap(); + + /** + * Servers currently doing authentication. Maps from organization to the challenge we sent. + */ + private static Map authenticatingServers = new ConcurrentHashMap<>(); /** * Start the server authentification. @@ -28,16 +32,14 @@ public class ServerAuthenticator * the organization of the server * @return encrypted random string */ - public static String startServerAuthentication( String organization ) + public static ByteBuffer startServerAuthentication( String organization ) { - String secret = RandomString.generate( 100, false ); - synchronized ( authenticatingServers ) { - authenticatingServers.put( organization, secret ); - log.info( "Server of organinzation '" + organization - + "' starts to authenticate. And got string: '" + secret - + "'" ); - } - return secret; + byte[] secret = RandomString.generateBinary( 100 ); + authenticatingServers.put( organization, secret ); + log.info( "Server of organinzation '" + organization + + "' starts to authenticate. And got string: '" + secret.length + + "'" ); + return ByteBuffer.wrap( secret ); } /** @@ -47,40 +49,24 @@ public class ServerAuthenticator * @param address * @param challengeResponse * @return - * @throws AuthenticationException + * @throws ServerAuthenticationException * @throws TException */ - public static ServerUser serverAuthenticate( String organization, - String address, ByteBuffer challengeResponse ) - throws AuthenticationException, TException + public static ServerUser serverAuthenticate( DbSatellite satellite, ByteBuffer challengeResponse ) + throws ServerAuthenticationException { - byte[] bytes = new byte[ 512 ]; - challengeResponse.get( bytes ); - - boolean result = false; - - AsymMessageVerifier verifier = null; - try { - verifier = new AsymMessageVerifier( organization ); - } catch ( Exception e ) { - throw new ServerAuthenticationException( ServerAuthenticationError.INVALID_ORGANIZATION, "Organization not found." ); - } + byte[] encryptedBytes = new byte[ challengeResponse.remaining() ]; + challengeResponse.get( encryptedBytes ); - try { - result = verifier.verifyMessage( bytes, authenticatingServers.get( organization ).getBytes() ); - } catch ( Exception e ) { - log.error( "Error while verifying message", e ); - throw new ServerAuthenticationException( ServerAuthenticationError.INVALID_KEY, "Could not verfiy key." ); - } + AsymEncryptionHandler verifier = new AsymEncryptionHandler( satellite.getPubkey() ); - if ( !result ) { - throw new ServerAuthenticationException( ServerAuthenticationError.INVALID_KEY, "Could not verfiy key." ); - } + if ( !verifier.verifyMessage( encryptedBytes, authenticatingServers.get( satellite.getOrganization() ) ) ) + throw new ServerAuthenticationException( ServerAuthenticationError.CHALLENGE_FAILED, "You failed the encryption challenge. private and public key don't seem to match." ); - log.info( "Server of organinzation '" + organization + " authenticated." ); + log.info( "Server of organinzation '" + satellite.getOrganization() + " authenticated." ); - authenticatingServers.remove( organization ); + authenticatingServers.remove( satellite.getOrganization() ); - return new ServerUser( organization, address ); + return new ServerUser( satellite.getOrganization(), satellite.getAddress() ); } } diff --git a/src/main/java/org/openslx/imagemaster/thrift/server/ImageServerHandler.java b/src/main/java/org/openslx/imagemaster/thrift/server/ImageServerHandler.java index 84e3ede..af78258 100644 --- a/src/main/java/org/openslx/imagemaster/thrift/server/ImageServerHandler.java +++ b/src/main/java/org/openslx/imagemaster/thrift/server/ImageServerHandler.java @@ -48,7 +48,7 @@ public class ImageServerHandler implements ImageServer.Iface } @Override - public String startServerAuthentication( String organization ) + public ByteBuffer startServerAuthentication( String organization ) throws ServerAuthenticationException { return ApiServer.startServerAuthentication( organization ); diff --git a/src/main/java/org/openslx/imagemaster/util/RandomString.java b/src/main/java/org/openslx/imagemaster/util/RandomString.java index fc4f9d3..0120344 100644 --- a/src/main/java/org/openslx/imagemaster/util/RandomString.java +++ b/src/main/java/org/openslx/imagemaster/util/RandomString.java @@ -29,4 +29,18 @@ public class RandomString } return result; } + + /** + * Generate random binary data. + * + * @param length number of bytes to generate + * @return the generated binary data, as byte array + */ + public static byte[] generateBinary( int length ) + { + byte[] result = new byte[ length ]; + random.nextBytes( result ); + return result; + } + } -- cgit v1.2.3-55-g7522