From c2fcf2370dc8c3137ea77ba94f6a12f1ab01a415 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 14 Oct 2014 19:20:26 +0200 Subject: Implement registerSatellite RPC --- .../openslx/imagemaster/db/DbPendingSatellite.java | 16 ++++++++ .../org/openslx/imagemaster/db/DbSatellite.java | 24 ++--------- .../org/openslx/imagemaster/server/ApiServer.java | 37 ++++++++++++++++- .../thrift/server/ImageServerHandler.java | 7 ++++ .../java/org/openslx/imagemaster/util/Util.java | 48 ++++++++++++++++++++++ 5 files changed, 110 insertions(+), 22 deletions(-) create mode 100644 src/main/java/org/openslx/imagemaster/db/DbPendingSatellite.java diff --git a/src/main/java/org/openslx/imagemaster/db/DbPendingSatellite.java b/src/main/java/org/openslx/imagemaster/db/DbPendingSatellite.java new file mode 100644 index 0000000..30ec5a2 --- /dev/null +++ b/src/main/java/org/openslx/imagemaster/db/DbPendingSatellite.java @@ -0,0 +1,16 @@ +package org.openslx.imagemaster.db; + +import org.apache.log4j.Logger; + +public class DbPendingSatellite +{ + + private static final Logger LOG = Logger.getLogger( DbPendingSatellite.class ); + + public static boolean add( String organizationId, String address, String modulus, String exponent ) + { + String publickey = "mod:" + modulus + " exp:" + exponent; + return MySQL.update( "INSERT INTO pending_satellite (dateline, organizationid, address, publickey)" + + " VALUES (UNIX_TIMESTAMP(), ?, ?, ?)", organizationId, address, publickey ) != 0; + } +} diff --git a/src/main/java/org/openslx/imagemaster/db/DbSatellite.java b/src/main/java/org/openslx/imagemaster/db/DbSatellite.java index 383377a..4d70bef 100644 --- a/src/main/java/org/openslx/imagemaster/db/DbSatellite.java +++ b/src/main/java/org/openslx/imagemaster/db/DbSatellite.java @@ -1,14 +1,13 @@ package org.openslx.imagemaster.db; import java.math.BigInteger; -import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.spec.InvalidKeySpecException; -import java.security.spec.RSAPublicKeySpec; import java.util.List; import org.apache.log4j.Logger; +import org.openslx.encryption.AsymKeyHolder; import org.openslx.imagemaster.thrift.iface.OrganizationData; /** @@ -21,18 +20,6 @@ public class DbSatellite private String organizationId, address, name, publickeyString; private PublicKey publickey = null; - private static final KeyFactory keyFact; - - static - { - KeyFactory kf; - try { - kf = KeyFactory.getInstance( "RSA" ); - } catch ( NoSuchAlgorithmException e ) { - kf = null; - } - keyFact = kf; - } public DbSatellite( String organizationId, String address, String name, String publickeyString ) { @@ -104,18 +91,15 @@ public class DbSatellite */ public PublicKey getPubkey() { - if ( publickey == null && keyFact != null && publickeyString != null ) { + if ( publickey == null && publickeyString != null ) { String parts[] = publickeyString.split( " " ); if ( parts.length != 2 ) return null; try { BigInteger mod = new BigInteger( parts[0] ); BigInteger exp = new BigInteger( parts[1] ); - RSAPublicKeySpec keySpec = new RSAPublicKeySpec( mod, exp ); - synchronized ( keyFact ) { - publickey = keyFact.generatePublic( keySpec ); - } - } catch ( InvalidKeySpecException e ) { + publickey = new AsymKeyHolder( null, exp, mod ).getPublicKey(); + } catch ( InvalidKeySpecException | NoSuchAlgorithmException e ) { LOG.info( "PubKey of " + this.name + " is not valid.", e ); } catch ( NumberFormatException e ) { LOG.info( "PubKey of " + this.name + " is corrupted in database!", e ); diff --git a/src/main/java/org/openslx/imagemaster/server/ApiServer.java b/src/main/java/org/openslx/imagemaster/server/ApiServer.java index ada6a21..0927e16 100644 --- a/src/main/java/org/openslx/imagemaster/server/ApiServer.java +++ b/src/main/java/org/openslx/imagemaster/server/ApiServer.java @@ -1,10 +1,16 @@ package org.openslx.imagemaster.server; import java.nio.ByteBuffer; +import java.security.Key; +import java.security.NoSuchAlgorithmException; +import java.security.spec.InvalidKeySpecException; import java.util.ArrayList; import java.util.List; +import org.apache.log4j.Logger; +import org.openslx.encryption.AsymKeyHolder; import org.openslx.imagemaster.db.DbImage; +import org.openslx.imagemaster.db.DbPendingSatellite; import org.openslx.imagemaster.db.DbSatellite; import org.openslx.imagemaster.db.DbUser; import org.openslx.imagemaster.serverconnection.ImageProcessor; @@ -31,6 +37,7 @@ import org.openslx.imagemaster.thrift.iface.SessionData; import org.openslx.imagemaster.thrift.iface.UploadData; import org.openslx.imagemaster.thrift.iface.UploadException; import org.openslx.imagemaster.thrift.iface.UserInfo; +import org.openslx.imagemaster.util.Util; /** * API Server This is where all the requests from the outside arrive. We don't @@ -46,6 +53,8 @@ import org.openslx.imagemaster.thrift.iface.UserInfo; public class ApiServer { + private static final Logger LOG = Logger.getLogger( ApiServer.class ); + /** * Request for authentication * @@ -167,10 +176,10 @@ public class ApiServer public static boolean publishUser( String serverSessionId, UserInfo user ) throws AuthorizationException { // Check session. - if (SessionManager.getSessionFromSessionId( serverSessionId ) == null) { + if ( SessionManager.getSessionFromSessionId( serverSessionId ) == null ) { throw new AuthorizationException( AuthorizationError.NOT_AUTHENTICATED, "Session ID not valid" ); } - if (DbUser.forLogin( user.userId ) == null) { + if ( DbUser.forLogin( user.userId ) == null ) { // User not known by server. Insert into server database. return DbUser.insertOrUpdate( user ); } @@ -200,4 +209,28 @@ public class ApiServer throw new AuthorizationException( AuthorizationError.NOT_AUTHENTICATED, "Session ID not valid" ); return DbImage.asImageDataList( page * 100, ( page + 1 ) * 100 ); } + + public static boolean registerSatellite( String organizationId, String address, String modulus, String exponent ) + { + if ( organizationId == null || address == null || exponent == null || modulus == null ) + return false; + Key newKey; + try { + newKey = new AsymKeyHolder( null, Util.tryToParseBigInt( exponent ), Util.tryToParseBigInt( modulus ) ).getPublicKey(); + } catch ( NoSuchAlgorithmException | InvalidKeySpecException e ) { + LOG.warn( "Invalid public key in registerOrganization for " + organizationId + " (" + address + ")", e ); + return false; + } + if ( newKey == null ) { + LOG.warn( "Uninstantiable public key in registerOrganization for " + organizationId + " (" + address + ")" ); + return false; + } + DbSatellite existing = DbSatellite.fromSuffix( organizationId ); + if ( existing != null ) { + Key existingKey = existing.getPubkey(); + if ( existingKey != null && Util.keysEqual( newKey, existingKey ) ) + return true; + } + return DbPendingSatellite.add( organizationId, address, modulus, exponent ); + } } 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 d28c736..2ef66c5 100644 --- a/src/main/java/org/openslx/imagemaster/thrift/server/ImageServerHandler.java +++ b/src/main/java/org/openslx/imagemaster/thrift/server/ImageServerHandler.java @@ -3,6 +3,7 @@ package org.openslx.imagemaster.thrift.server; import java.nio.ByteBuffer; import java.util.List; +import org.apache.thrift.TException; import org.openslx.imagemaster.server.ApiServer; import org.openslx.imagemaster.thrift.iface.AuthenticationException; import org.openslx.imagemaster.thrift.iface.AuthorizationException; @@ -98,4 +99,10 @@ public class ImageServerHandler implements ImageServer.Iface { return ApiServer.getPublicImages( sessionId, page ); } + + @Override + public boolean registerSatellite( String organizationId, String address, String modulus, String exponent ) + { + return ApiServer.registerSatellite( organizationId, address, modulus, exponent ); + } } diff --git a/src/main/java/org/openslx/imagemaster/util/Util.java b/src/main/java/org/openslx/imagemaster/util/Util.java index ffd3106..a524953 100644 --- a/src/main/java/org/openslx/imagemaster/util/Util.java +++ b/src/main/java/org/openslx/imagemaster/util/Util.java @@ -1,6 +1,11 @@ package org.openslx.imagemaster.util; import java.io.File; +import java.math.BigInteger; +import java.security.Key; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.util.Arrays; import java.util.Random; import org.apache.log4j.Logger; @@ -120,6 +125,21 @@ public class Util } } + /** + * Tries to parse a bigint. Returns null on error. + * + * @param s The strig to parse + * @return The parsed bigint + */ + public static BigInteger tryToParseBigInt( String s ) + { + try { + return new BigInteger( s ); + } catch ( NumberFormatException e ) { + return null; + } + } + public static int getNumberOfBlocks( long fileSize, int blockSize ) { int blocks = (int) ( fileSize / blockSize ); @@ -136,4 +156,32 @@ public class Util return fileName; } + /** + * Checks whether the two given keys are equal. Works for + * public and private keys. + * + * @param k1 first key + * @param k2 second key + * @return true if equal + */ + public static boolean keysEqual( Key k1, Key k2 ) + { + if ( k1 instanceof RSAPublicKey && k2 instanceof RSAPublicKey ) + { + RSAPublicKey rsa1 = (RSAPublicKey)k1; + RSAPublicKey rsa2 = (RSAPublicKey)k2; + return rsa1.getModulus().equals( rsa2.getModulus() ) + && rsa1.getPublicExponent().equals( rsa2.getPublicExponent() ); + } + + if ( k1 instanceof RSAPrivateKey && k2 instanceof RSAPrivateKey ) + { + RSAPrivateKey rsa1 = (RSAPrivateKey)k1; + RSAPrivateKey rsa2 = (RSAPrivateKey)k2; + return rsa1.getModulus().equals( rsa2.getModulus() ) + && rsa1.getPrivateExponent().equals( rsa2.getPrivateExponent() ); + } + return Arrays.equals( k1.getEncoded(), k2.getEncoded() ); + } + } -- cgit v1.2.3-55-g7522