package org.openslx.imagemaster.serversession; import java.nio.ByteBuffer; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.apache.log4j.Logger; import org.apache.thrift.TException; import org.openslx.encryption.AsymEncryptionHandler; import org.openslx.imagemaster.db.DbSatellite; import org.openslx.imagemaster.thrift.iface.AuthenticationError; import org.openslx.imagemaster.thrift.iface.AuthenticationException; import org.openslx.imagemaster.util.RandomString; /** * Authenticating a server with message signing. */ public class ServerAuthenticator { private static Logger log = Logger.getLogger( ServerAuthenticator.class ); /** * Servers currently doing authentication. Maps from organization to the challenge we sent. */ private static Map authenticatingServers = new ConcurrentHashMap<>(); /** * Start the server authentification. * * @param organization * the organization of the server * @return encrypted random string */ public static ByteBuffer startServerAuthentication( String organization ) { 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 ); } /** * Authenticate with the challengeResponse. * * @param organizationId Is already verified. * @param address * @param challengeResponse * @return * @throws ServerAuthenticationException * @throws TException */ public static ServerUser serverAuthenticate( DbSatellite satellite, ByteBuffer challengeResponse ) throws AuthenticationException { byte[] encryptedBytes = new byte[ challengeResponse.remaining() ]; challengeResponse.get( encryptedBytes ); AsymEncryptionHandler verifier = new AsymEncryptionHandler( satellite.getPubkey() ); if ( !verifier.verifyMessage( encryptedBytes, authenticatingServers.get( satellite.getOrganizationId() ) ) ) throw new AuthenticationException( AuthenticationError.CHALLENGE_FAILED, "You failed the encryption challenge. private and public key don't seem to match." ); log.info( "Server of organinzation " + satellite.getName() + " (" + satellite.getOrganizationId() + ") authenticated." ); authenticatingServers.remove( satellite.getOrganizationId() ); return new ServerUser( satellite.getOrganizationId(), satellite.getAddress() ); } }