diff options
| author | Simon Rettberg | 2014-04-24 18:59:35 +0200 |
|---|---|---|
| committer | Simon Rettberg | 2014-04-24 18:59:35 +0200 |
| commit | ed787b6f67954faab790cab107503eac8e6aad3c (patch) | |
| tree | 6f05300170e670ab5db0ccda62bb918d0371b7ad /src/main/java/org/openslx/imagemaster/server | |
| parent | Fix name of format style (diff) | |
| parent | Add FTPS to MasterFtpServer (diff) | |
| download | masterserver-ed787b6f67954faab790cab107503eac8e6aad3c.tar.gz masterserver-ed787b6f67954faab790cab107503eac8e6aad3c.tar.xz masterserver-ed787b6f67954faab790cab107503eac8e6aad3c.zip | |
Merge branch 'master' of dnbd3:bwlp/masterserver
Diffstat (limited to 'src/main/java/org/openslx/imagemaster/server')
4 files changed, 248 insertions, 164 deletions
diff --git a/src/main/java/org/openslx/imagemaster/server/ApiServer.java b/src/main/java/org/openslx/imagemaster/server/ApiServer.java index df0aa3a..c88bd05 100644 --- a/src/main/java/org/openslx/imagemaster/server/ApiServer.java +++ b/src/main/java/org/openslx/imagemaster/server/ApiServer.java @@ -4,6 +4,7 @@ import java.io.File; import org.apache.log4j.Logger; import org.apache.thrift.TException; +import org.openslx.imagemaster.App; import org.openslx.imagemaster.Globals; import org.openslx.imagemaster.db.DbSatellite; import org.openslx.imagemaster.db.ImageProcessor; @@ -39,8 +40,9 @@ import org.openslx.imagemaster.thrift.iface.UserInfo; * This will be accessed from multiple threads, so use synchronization when * needed (or in doubt) */ -public class ApiServer { - private static Logger log = Logger.getLogger(ApiServer.class); +public class ApiServer +{ + private static Logger log = Logger.getLogger( ApiServer.class ); /** * Request for authentication @@ -50,17 +52,18 @@ public class ApiServer { * @return SessionData struct with session id/token iff login successful * @throws AuthenticationException if login not successful */ - public static SessionData authenticate(String login, String password) - throws AuthenticationException { - if (login == null || password == null) { + public static SessionData authenticate( String login, String password ) + throws AuthenticationException + { + if ( login == null || password == null ) { throw new AuthenticationException( AuthenticationError.INVALID_CREDENTIALS, - "Empty username or password!"); + "Empty username or password!" ); } - final User user = Authenticator.authenticate(login, password); + final User user = Authenticator.authenticate( login, password ); - final Session session = new Session(user); - return SessionManager.addSession(session); + final Session session = new Session( user ); + return SessionManager.addSession( session ); } /** @@ -70,121 +73,131 @@ public class ApiServer { * @return UserInfo struct for given token's user * @throws InvalidTokenException if no user matches the given token */ - public static UserInfo getUserFromToken(String token) - throws InvalidTokenException { - final Session session = SessionManager.getSession(token); - if (session == null) + public static UserInfo getUserFromToken( String token ) + throws InvalidTokenException + { + final Session session = SessionManager.getSession( token ); + if ( session == null ) throw new InvalidTokenException(); - return new UserInfo(session.getUserId(), session.getFirstName(), - session.getLastName(), session.getEMail()); + return new UserInfo( session.getUserId(), session.getFirstName(), + session.getLastName(), session.getEMail() ); } /** * Request ftp credentials to upload a new image to the masterserver. + * * @param imageDescription MetaData of the new image * @param serverSessionData the session data of the authenticated uni/hs server * @return the genereated ftp credentials * @throws AuthorizationException if the uni/hs server has no valid session * @throws TException */ - public static FtpCredentials submitImage(String serverSessionId, - ImageData imageDescription) throws AuthorizationException, - TException { - if (ServerSessionManager.getSession(serverSessionId) == null) { - throw new AuthorizationException(AuthorizationError.NOT_AUTHENTICATED, "No valid serverSessionData"); + public static FtpCredentials submitImage( String serverSessionId, + ImageData imageDescription ) throws AuthorizationException, + TException + { + if ( ServerSessionManager.getSession( serverSessionId ) == null ) { + throw new AuthorizationException( AuthorizationError.NOT_AUTHENTICATED, "No valid serverSessionData" ); } - + // create new user - FtpCredentials ftpCredentials = Globals.ftpServer.addUser(serverSessionId); - - if (ftpCredentials == null) { - log.error("Could not create ftp credentials"); + FtpCredentials ftpCredentials = App.ftpServer.addUser( serverSessionId ); + + if ( ftpCredentials == null ) { + log.error( "Could not create ftp credentials" ); return null; } - - if (!ImageProcessor.addImageDataToProcess(imageDescription, ftpCredentials.username)) { - Globals.ftpServer.removeUser(serverSessionId); - throw new TException("ImageData is not valid."); + + if ( !ImageProcessor.addImageDataToProcess( imageDescription, ftpCredentials.username ) ) { + App.ftpServer.removeUser( serverSessionId ); + throw new TException( "ImageData is not valid." ); } - + return ftpCredentials; } /** * Start the server authentication of a uni/hs satellite server. + * * @param organization the organization that the server belongs to * @return a random string that needs to be encrypted with the private - * key of the requesting satellite server + * key of the requesting satellite server * @throws ServerAuthenticationException when organization is invalid/unknown */ - public static String startServerAuthentication(String organization) - throws ServerAuthenticationException { - if (organization == null || organization == "") { - throw new ServerAuthenticationException(ServerAuthenticationError.INVALID_ORGANIZATION, "Empty organization"); + public static String startServerAuthentication( String organization ) + throws ServerAuthenticationException + { + if ( organization == null || organization == "" ) { + throw new ServerAuthenticationException( ServerAuthenticationError.INVALID_ORGANIZATION, "Empty organization" ); } - if (DbSatellite.fromOrganization(organization) == null) { - throw new ServerAuthenticationException(ServerAuthenticationError.INVALID_ORGANIZATION, "Unknown organization"); + if ( DbSatellite.fromOrganization( organization ) == null ) { + throw new ServerAuthenticationException( ServerAuthenticationError.INVALID_ORGANIZATION, "Unknown organization" ); } - return ServerAuthenticator.startServerAuthentication(organization); + return ServerAuthenticator.startServerAuthentication( organization ); } /** * Authenticate the uni/hs satellite server with the encrypted string. + * * @param organization the organization that the server belongs to * @param challengeResponse the encrypted string * @return session data iff the authentication was successful * @throws AuthenticationException * @throws TException */ - public static ServerSessionData serverAuthenticate(String organization, - String challengeResponse) throws AuthenticationException, - TException { - if (organization == null || challengeResponse == null) { - throw new ServerAuthenticationException(ServerAuthenticationError.INVALID_ORGANIZATION, "Empty organization or challengeResponse"); + public static ServerSessionData serverAuthenticate( String organization, + String challengeResponse ) throws AuthenticationException, + TException + { + if ( organization == null || challengeResponse == null ) { + throw new ServerAuthenticationException( ServerAuthenticationError.INVALID_ORGANIZATION, "Empty organization or challengeResponse" ); } - DbSatellite satellite = DbSatellite.fromOrganization(organization); - if (satellite == 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" ); } final ServerUser serverUser = ServerAuthenticator.serverAuthenticate( - organization, satellite.getAddress(), challengeResponse); - - final ServerSession session = new ServerSession(serverUser); - return ServerSessionManager.addSession(session); + organization, satellite.getAddress(), challengeResponse ); + + final ServerSession session = new ServerSession( serverUser ); + return ServerSessionManager.addSession( session ); } /** * Tell the masterserver that the image upload finished. + * * @param serverSessionId The session id of the hs/uni server * @param imageDescription the description of the uploaded image * @return if nothing went wrong * @throws AuthorizationException if no valid session exists */ - public static boolean finishedUpload(String serverSessionId, - ImageData imageDescription) throws AuthorizationException { + public static boolean finishedUpload( String serverSessionId, + ImageData imageDescription ) throws AuthorizationException + { // check if valid session exists - if (ServerSessionManager.getSession(serverSessionId) == null) { - throw new AuthorizationException(AuthorizationError.NOT_AUTHENTICATED, "No valid serverSessionData"); + if ( ServerSessionManager.getSession( serverSessionId ) == null ) { + throw new AuthorizationException( AuthorizationError.NOT_AUTHENTICATED, "No valid serverSessionData" ); } - + // process the image - String username = Globals.ftpServer.getCredentialsFromSessionId(serverSessionId).username; - - File userDirectory = new File(Globals.properties.getProperty(Globals.ftpBaseDir) + "/" + username); + String username = App.ftpServer.getCredentialsFromSessionId( serverSessionId ).username; + + File userDirectory = new File( Globals.getPropertyString( Globals.PropString.FTPBASEDIR ) + "/" + username ); File[] list = userDirectory.listFiles(); - - if (list.length != 1) return false; - - log.info(username + " is done with upload"); - + + if ( list.length != 1 ) + return false; + + log.info( username + " is done with upload" ); + // remove user that is not needed anymore - Globals.ftpServer.removeUser(username); - log.info("Removed user: " + username); - - ImageProcessor.processImageAfterUpload(username, list[0].getName()); - - Globals.ftpServer.removeUser(serverSessionId); - + App.ftpServer.removeUser( username ); + log.info( "Removed user: " + username ); + + ImageProcessor.processImageAfterUpload( username, list[0].getName() ); + + App.ftpServer.removeUser( serverSessionId ); + return true; } diff --git a/src/main/java/org/openslx/imagemaster/server/FtpCredentialsScheduler.java b/src/main/java/org/openslx/imagemaster/server/FtpCredentialsScheduler.java new file mode 100644 index 0000000..ba88f33 --- /dev/null +++ b/src/main/java/org/openslx/imagemaster/server/FtpCredentialsScheduler.java @@ -0,0 +1,63 @@ +package org.openslx.imagemaster.server; + +import java.io.File; +import java.util.Date; +import java.util.Map; +import java.util.Timer; +import java.util.TimerTask; + +import org.apache.log4j.Logger; +import org.openslx.imagemaster.App; +import org.openslx.imagemaster.Globals; +import org.openslx.imagemaster.thrift.iface.FtpCredentials; +import org.openslx.imagemaster.util.Util; + +public class FtpCredentialsScheduler extends TimerTask +{ + private static Logger log = Logger.getLogger( FtpCredentialsScheduler.class ); + + public static final long timeout = Long.valueOf( Globals.getPropertyInt( Globals.PropInt.FTPTIMEOUT ) ) * 60L * 1000L; // timeout in ms + + @Override + public void run() + { + // check all folders + for ( Map.Entry<String, FtpCredentials> entry : App.ftpServer.users.entrySet() ) { + String sessionId = entry.getKey(); + String username = entry.getValue().username; + File dir = new File( Globals.getPropertyString( Globals.PropString.FTPBASEDIR ) + "/" + username ); + if ( !dir.exists() ) + continue; + File[] list = dir.listFiles(); + if ( list.length == 1 ) { + if ( ( new Date().getTime() - list[0].lastModified() ) >= timeout ) { + log.info( username + "'s files are too old. Deleting him and his folder." ); + Util.deleteFolder( dir ); + App.ftpServer.removeUser( sessionId ); + } + } else if ( list.length > 1 ) { + log.info( username + " uploaded too many files. Deleting his account and his folder." ); + Util.deleteFolder( dir ); + App.ftpServer.removeUser( sessionId ); + } else { + // check the creation time of the user + if ( ( new Date().getTime() - App.ftpServer.timeouts.get( username ).getTime() ) >= timeout ) { + // remove user and his folder + Util.deleteFolder( dir ); + App.ftpServer.removeUser( sessionId ); + log.info( username + " did nothing for too long. Deleting him and his folder" ); + } + } + } + //TODO: remove image from process list + } + + public static void startScheduling() + { + Timer timer = new Timer(); + + // start timer now and fire every 60 seconds + timer.schedule( new FtpCredentialsScheduler(), 0, 60000 ); + } + +} diff --git a/src/main/java/org/openslx/imagemaster/server/MasterFtpServer.java b/src/main/java/org/openslx/imagemaster/server/MasterFtpServer.java index d1ec14f..de0d758 100644 --- a/src/main/java/org/openslx/imagemaster/server/MasterFtpServer.java +++ b/src/main/java/org/openslx/imagemaster/server/MasterFtpServer.java @@ -13,6 +13,7 @@ import org.apache.ftpserver.ftplet.FtpException; import org.apache.ftpserver.ftplet.Ftplet; import org.apache.ftpserver.ftplet.UserManager; import org.apache.ftpserver.listener.ListenerFactory; +import org.apache.ftpserver.ssl.SslConfigurationFactory; import org.apache.ftpserver.usermanager.PropertiesUserManagerFactory; import org.apache.ftpserver.usermanager.SaltedPasswordEncryptor; import org.apache.ftpserver.usermanager.impl.BaseUser; @@ -22,7 +23,8 @@ import org.openslx.imagemaster.Globals; import org.openslx.imagemaster.thrift.iface.FtpCredentials; import org.openslx.imagemaster.util.RandomString; -public class MasterFtpServer implements Runnable { +public class MasterFtpServer implements Runnable +{ private static Logger log = Logger.getLogger( MasterFtpServer.class ); private FtpServer server; private UserManager userManager; @@ -30,96 +32,111 @@ public class MasterFtpServer implements Runnable { public final HashMap<String, FtpCredentials> users = new HashMap<>(); // key: ftpUsername, value: createTime public final HashMap<String, Date> timeouts = new HashMap<>(); - - public MasterFtpServer(int port, String adminUsername, String adminPassword, String ftproot) { + private boolean ini = false; + + public void init( int port ) + { + if ( ini ) + return; + FtpServerFactory serverFactory = new FtpServerFactory(); ListenerFactory factory = new ListenerFactory(); + + // config ssl + SslConfigurationFactory sslConfigFactory = new SslConfigurationFactory(); + sslConfigFactory.setKeystoreFile( new File( "./keyfiles/ftp.jks" ) ); + sslConfigFactory.setKeyAlias( "ftp" ); + sslConfigFactory.setKeystorePassword( "password" ); + // set the port of the listener - factory.setPort(port); - + factory.setPort( port ); + factory.setSslConfiguration( sslConfigFactory.createSslConfiguration() ); + factory.setImplicitSsl( true ); + // replace the default listener - serverFactory.addListener("default", factory.createListener()); - + serverFactory.addListener( "default", factory.createListener() ); + // create user manager - PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory(); - userManagerFactory.setFile(new File("src/main/properties/ftp.properties")); - userManagerFactory.setPasswordEncryptor(new SaltedPasswordEncryptor()); - userManager = userManagerFactory.createUserManager(); - - // create new admin user - //addUser(adminUsername, adminPassword, ftproot, true); - serverFactory.setUserManager(userManager); - + PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory(); + userManagerFactory.setFile( new File( "src/main/properties/ftp.properties" ) ); + userManagerFactory.setPasswordEncryptor( new SaltedPasswordEncryptor() ); + userManager = userManagerFactory.createUserManager(); + serverFactory.setUserManager( userManager ); + // add the Ftplet HashMap<String, Ftplet> map = new HashMap<String, Ftplet>(); - map.put("Ftplet1", new MasterFtplet()); - serverFactory.setFtplets(map); - + map.put( "Ftplet1", new MasterFtplet() ); + serverFactory.setFtplets( map ); + // start the server server = serverFactory.createServer(); + ini = true; } - public FtpCredentials addUser(final String serverSessionId) { - // TODO: enable SSL - + public FtpCredentials addUser( final String serverSessionId ) + { FtpCredentials ftpCredentials = null; - - String generatedUser = RandomString.generate(10, false); - String generatedPass = RandomString.generate(16, true); - - String dir = Globals.properties.getProperty(Globals.ftpBaseDir) + "/" + + String generatedUser = RandomString.generate( 10, false ); + String generatedPass = RandomString.generate( 16, true ); + + String dir = Globals.getPropertyString( Globals.PropString.FTPBASEDIR ) + "/" + generatedUser + "/"; - - if (!new File(dir).mkdir()) { + + if ( !new File( dir ).mkdir() ) { return ftpCredentials; } - BaseUser user = new BaseUser(); - user.setName(generatedUser); - user.setPassword(generatedPass); - user.setHomeDirectory(dir); - - List<Authority> authorities = new ArrayList<Authority>(); - authorities.add(new WritePermission()); - user.setAuthorities(authorities); - - try { - userManager.save(user); - ftpCredentials = new FtpCredentials(generatedUser, generatedPass); - users.put(serverSessionId, ftpCredentials); - timeouts.put(ftpCredentials.username, new Date()); - } catch (FtpException e) { - } - - log.info("Generated user/pass: " + generatedUser + "\t" - + generatedPass + "\n with home dir: " + dir); - - return ftpCredentials; + BaseUser user = new BaseUser(); + user.setName( generatedUser ); + user.setPassword( generatedPass ); + user.setHomeDirectory( dir ); + + List<Authority> authorities = new ArrayList<Authority>(); + authorities.add( new WritePermission() ); + user.setAuthorities( authorities ); + + try { + userManager.save( user ); + ftpCredentials = new FtpCredentials( generatedUser, generatedPass ); + users.put( serverSessionId, ftpCredentials ); + timeouts.put( ftpCredentials.username, new Date() ); + } catch ( FtpException e ) { + } + + log.info( "Generated user/pass: " + generatedUser + "\t" + + generatedPass + "\n with home dir: " + dir ); + + return ftpCredentials; } - - public boolean removeUser(final String serverSessionId) { - if (!users.containsKey(serverSessionId)) return false; - + + public boolean removeUser( final String serverSessionId ) + { + if ( !users.containsKey( serverSessionId ) ) + return false; + try { - userManager.delete(users.get(serverSessionId).username); + userManager.delete( users.get( serverSessionId ).username ); // remove user from both maps - timeouts.remove(users.remove(serverSessionId).username); + timeouts.remove( users.remove( serverSessionId ).username ); return true; - } catch (FtpException e) { + } catch ( FtpException e ) { return false; } } - - public FtpCredentials getCredentialsFromSessionId(String serverSessionId) { - return users.get(serverSessionId); + + public FtpCredentials getCredentialsFromSessionId( String serverSessionId ) + { + return users.get( serverSessionId ); } @Override - public void run() { + public void run() + { try { log.info( "Starting FTP Sever" ); server.start(); - } catch (FtpException e1) { + } catch ( FtpException e1 ) { e1.printStackTrace(); } } diff --git a/src/main/java/org/openslx/imagemaster/server/MasterFtplet.java b/src/main/java/org/openslx/imagemaster/server/MasterFtplet.java index 479729d..a8c1cbe 100644 --- a/src/main/java/org/openslx/imagemaster/server/MasterFtplet.java +++ b/src/main/java/org/openslx/imagemaster/server/MasterFtplet.java @@ -9,63 +9,54 @@ import org.apache.ftpserver.ftplet.FtpSession; import org.apache.ftpserver.ftplet.Ftplet; import org.apache.ftpserver.ftplet.FtpletContext; import org.apache.ftpserver.ftplet.FtpletResult; -import org.apache.ftpserver.ftplet.UserManager; import org.apache.log4j.Logger; -import org.openslx.imagemaster.db.ImageProcessor; -public class MasterFtplet implements Ftplet { - private static Logger log = Logger.getLogger(Ftplet.class); - private UserManager userManager; +public class MasterFtplet implements Ftplet +{ + private static Logger log = Logger.getLogger( Ftplet.class ); @Override - public void init(FtpletContext ftpletContext) throws FtpException { - userManager = ftpletContext.getUserManager(); + public void init( FtpletContext ftpletContext ) throws FtpException + { + // not used } @Override - public void destroy() { + public void destroy() + { // not used } @Override - public FtpletResult beforeCommand(FtpSession session, FtpRequest request) - throws FtpException, IOException { - if (session.getUser() != null) { - log.info(session.getUser().getName() + " issued command: " + request.getRequestLine()); + public FtpletResult beforeCommand( FtpSession session, FtpRequest request ) + throws FtpException, IOException + { + if ( session.getUser() != null ) { + log.info( session.getUser().getName() + " issued command: " + request.getRequestLine() ); } return null; } @Override - public FtpletResult afterCommand(FtpSession session, FtpRequest request, - FtpReply reply) throws FtpException, IOException { - if (session.getUser() != null) { - String username = session.getUser().getName(); - String command = request.getRequestLine(); - log.info(username + " is done with command: " + command); - if (request.getCommand().equals("STOR")) { - try { - userManager.delete(username); - } catch (FtpException e) { - } finally { - log.info("Stored file and deleted user: '" + username + "'"); - ImageProcessor.processImageAfterUpload(username, command.split(" ")[1]); - } - } - } + public FtpletResult afterCommand( FtpSession session, FtpRequest request, + FtpReply reply ) throws FtpException, IOException + { + // not used return null; } @Override - public FtpletResult onConnect(FtpSession session) throws FtpException, - IOException { + public FtpletResult onConnect( FtpSession session ) throws FtpException, + IOException + { // not used return null; } @Override - public FtpletResult onDisconnect(FtpSession session) throws FtpException, - IOException { + public FtpletResult onDisconnect( FtpSession session ) throws FtpException, + IOException + { // not used return null; } |
