summaryrefslogtreecommitdiffstats
path: root/src/main/java/org/openslx/imagemaster/ftp
diff options
context:
space:
mode:
authorNils Schwabe2014-04-25 14:28:56 +0200
committerNils Schwabe2014-04-25 14:28:56 +0200
commit40d528627efc309681496b47d66558e15eb3fe5e (patch)
tree4cb7ba77b4b55ecb0b29a734c782b68d6926d441 /src/main/java/org/openslx/imagemaster/ftp
parentAdd FTPS to MasterFtpServer (diff)
downloadmasterserver-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')
-rw-r--r--src/main/java/org/openslx/imagemaster/ftp/FtpCredentialsScheduler.java63
-rw-r--r--src/main/java/org/openslx/imagemaster/ftp/ImageProcessor.java90
-rw-r--r--src/main/java/org/openslx/imagemaster/ftp/MasterFtpServer.java144
-rw-r--r--src/main/java/org/openslx/imagemaster/ftp/MasterFtplet.java64
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;
+ }
+
+}