diff options
| author | Nils Schwabe | 2014-04-25 14:28:56 +0200 |
|---|---|---|
| committer | Nils Schwabe | 2014-04-25 14:28:56 +0200 |
| commit | 40d528627efc309681496b47d66558e15eb3fe5e (patch) | |
| tree | 4cb7ba77b4b55ecb0b29a734c782b68d6926d441 /src/main/java/org/openslx/imagemaster/ftp | |
| parent | Add FTPS to MasterFtpServer (diff) | |
| download | masterserver-40d528627efc309681496b47d66558e15eb3fe5e.tar.gz masterserver-40d528627efc309681496b47d66558e15eb3fe5e.tar.xz masterserver-40d528627efc309681496b47d66558e15eb3fe5e.zip | |
Finally: Add _real_ server authentication. (this challengeresponse thing)
Diffstat (limited to 'src/main/java/org/openslx/imagemaster/ftp')
4 files changed, 361 insertions, 0 deletions
diff --git a/src/main/java/org/openslx/imagemaster/ftp/FtpCredentialsScheduler.java b/src/main/java/org/openslx/imagemaster/ftp/FtpCredentialsScheduler.java new file mode 100644 index 0000000..b0b23aa --- /dev/null +++ b/src/main/java/org/openslx/imagemaster/ftp/FtpCredentialsScheduler.java @@ -0,0 +1,63 @@ +package org.openslx.imagemaster.ftp; + +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/ftp/ImageProcessor.java b/src/main/java/org/openslx/imagemaster/ftp/ImageProcessor.java new file mode 100644 index 0000000..4c09907 --- /dev/null +++ b/src/main/java/org/openslx/imagemaster/ftp/ImageProcessor.java @@ -0,0 +1,90 @@ +package org.openslx.imagemaster.ftp; + +import java.io.File; +import java.util.HashMap; + +import org.apache.log4j.Logger; +import org.openslx.imagemaster.Globals; +import org.openslx.imagemaster.db.DbImage; +import org.openslx.imagemaster.thrift.iface.ImageData; + +public class ImageProcessor +{ + + private static Logger log = Logger.getLogger( ImageProcessor.class ); + private static HashMap<String, ImageData> images = new HashMap<>(); + + /** + * Processes an image after upload + * + * @param username the user that uploaded the file + * @param filename the name of the file that was uploaded (_no_ absolute path) + * @return + */ + public static boolean processImageAfterUpload( String username, String filename ) + { + if ( !images.containsKey( username ) ) { + return false; + } + + log.info( "Will now process '" + filename + "' from user '" + username + + "'" ); + + // move image to right location + String oldFileName = Globals.getPropertyString( Globals.PropString.FTPBASEDIR ) + "/" + username + "/" + filename; + String newFileName = Globals.getPropertyString( Globals.PropString.IMAGEDIR ) + "/" + images.get( username ).uuid; + + File imageFile = new File( oldFileName ); + + if ( !imageFile.exists() ) { + // image file does not exist + return false; + } + + imageFile.renameTo( new File( newFileName ) ); + + log.info( "Moved file from " + oldFileName + " to " + newFileName ); + + File tempUserDir = new File( Globals.getPropertyString( Globals.PropString.FTPBASEDIR ) + "/" + username ); + tempUserDir.delete(); + + // update database + DbImage.update( images.get( username ), newFileName ); + log.info( "Updated db: " + images.get( username ).uuid ); + + images.remove( username ); + return true; + } + + /** + * Try to add imageData to database. + * + * @param imageData + * the data for the image to add + * @return false if submit fails + */ + public static boolean addImageDataToProcess( ImageData imageData, String username ) + { + log.info( "Adding image to process list: " + imageData.imageName + ", submitted by " + username ); + + if ( imageData.uuid.isEmpty() || imageData.imageName.isEmpty() + || imageData.imageOwner.isEmpty() || imageData.conentOperatingSystem.isEmpty() + || imageData.imageShortDescription.isEmpty() + || imageData.imageLongDescription.isEmpty() ) { + return false; + } + + // TODO: check some regex? + + if ( DbImage.exists( imageData ) ) { + return false; + } + + // if everything went fine, add image to db + DbImage.insert( imageData ); + + // and to processinglist + images.put( username, imageData ); + return true; + } +} diff --git a/src/main/java/org/openslx/imagemaster/ftp/MasterFtpServer.java b/src/main/java/org/openslx/imagemaster/ftp/MasterFtpServer.java new file mode 100644 index 0000000..992c49a --- /dev/null +++ b/src/main/java/org/openslx/imagemaster/ftp/MasterFtpServer.java @@ -0,0 +1,144 @@ +package org.openslx.imagemaster.ftp; + +import java.io.File; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; + +import org.apache.ftpserver.FtpServer; +import org.apache.ftpserver.FtpServerFactory; +import org.apache.ftpserver.ftplet.Authority; +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; +import org.apache.ftpserver.usermanager.impl.WritePermission; +import org.apache.log4j.Logger; +import org.openslx.imagemaster.Globals; +import org.openslx.imagemaster.Globals.PropString; +import org.openslx.imagemaster.thrift.iface.FtpCredentials; +import org.openslx.imagemaster.util.RandomString; + +public class MasterFtpServer implements Runnable +{ + private static Logger log = Logger.getLogger( MasterFtpServer.class ); + private FtpServer server; + private UserManager userManager; + // key: serverSessionId, value: FtpCredentials + public final HashMap<String, FtpCredentials> users = new HashMap<>(); + // key: ftpUsername, value: createTime + public final HashMap<String, Date> timeouts = new HashMap<>(); + 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( Globals.getPropertyString( PropString.KEYSTOREFILE ) ) ); + sslConfigFactory.setKeyAlias( Globals.getPropertyString( PropString.KEYSTOREALIAS ) ); + sslConfigFactory.setKeystorePassword( Globals.getPropertyString( PropString.KEYSTOREPASSWORD ) ); + + // set the port of the listener + factory.setPort( port ); + factory.setSslConfiguration( sslConfigFactory.createSslConfiguration() ); + factory.setImplicitSsl( true ); + + // replace the default listener + 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(); + serverFactory.setUserManager( userManager ); + + // add the Ftplet + HashMap<String, Ftplet> map = new HashMap<String, Ftplet>(); + map.put( "Ftplet1", new MasterFtplet() ); + serverFactory.setFtplets( map ); + + // start the server + server = serverFactory.createServer(); + ini = true; + } + + public FtpCredentials addUser( final String serverSessionId ) + { + FtpCredentials ftpCredentials = null; + + 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() ) { + 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; + + try { + userManager.delete( users.get( serverSessionId ).username ); + // remove user from both maps + timeouts.remove( users.remove( serverSessionId ).username ); + return true; + } catch ( FtpException e ) { + return false; + } + } + + public FtpCredentials getCredentialsFromSessionId( String serverSessionId ) + { + return users.get( serverSessionId ); + } + + @Override + public void run() + { + try { + log.info( "Starting FTP Sever" ); + server.start(); + } catch ( FtpException e1 ) { + e1.printStackTrace(); + } + } +} diff --git a/src/main/java/org/openslx/imagemaster/ftp/MasterFtplet.java b/src/main/java/org/openslx/imagemaster/ftp/MasterFtplet.java new file mode 100644 index 0000000..3c73dba --- /dev/null +++ b/src/main/java/org/openslx/imagemaster/ftp/MasterFtplet.java @@ -0,0 +1,64 @@ +package org.openslx.imagemaster.ftp; + +import java.io.IOException; + +import org.apache.ftpserver.ftplet.FtpException; +import org.apache.ftpserver.ftplet.FtpReply; +import org.apache.ftpserver.ftplet.FtpRequest; +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.log4j.Logger; + +public class MasterFtplet implements Ftplet +{ + private static Logger log = Logger.getLogger( Ftplet.class ); + + @Override + public void init( FtpletContext ftpletContext ) throws FtpException + { + // not used + } + + @Override + 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() ); + } + return null; + } + + @Override + 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 + { + // not used + return null; + } + + @Override + public FtpletResult onDisconnect( FtpSession session ) throws FtpException, + IOException + { + // not used + return null; + } + +} |
