diff options
Diffstat (limited to 'src')
9 files changed, 201 insertions, 62 deletions
diff --git a/src/main/java/org/openslx/imagemaster/App.java b/src/main/java/org/openslx/imagemaster/App.java index 3a309c5..aba2cd6 100644 --- a/src/main/java/org/openslx/imagemaster/App.java +++ b/src/main/java/org/openslx/imagemaster/App.java @@ -25,6 +25,10 @@ public class App { stream = new BufferedInputStream(new FileInputStream( "config/global.properties")); Globals.properties.load(stream); + if (!Globals.propertiesValid()) { + log.error("Config file contains errors."); + System.exit(1); + } } catch (IOException e) { log.error("Could not load config file. Quitting."); error = true; diff --git a/src/main/java/org/openslx/imagemaster/Globals.java b/src/main/java/org/openslx/imagemaster/Globals.java index b766b27..653e255 100644 --- a/src/main/java/org/openslx/imagemaster/Globals.java +++ b/src/main/java/org/openslx/imagemaster/Globals.java @@ -2,10 +2,57 @@ package org.openslx.imagemaster; import java.util.Properties; +import org.apache.commons.lang3.StringUtils; import org.openslx.imagemaster.server.MasterFtpServer; public class Globals { public static final Properties properties = new Properties(); + public static final MasterFtpServer ftpServer = new MasterFtpServer(2221, "admin", "SI*HoZCC!]V)p>B2", Globals.properties.getProperty("ftp_base_dir")); + + // properties + public static final String ftpBaseDir = "ftp_base_dir"; + public static final String imageDir = "image_dir"; + public static final String ldapPort = "ldap_port"; + public static final String ldapHost = "ldap_host"; + public static final String ldapSsl = "ldap_ssl"; + public static final String ldapBindQuery = "ldap_bind_query"; + public static final String ldapSearchBaseDn = "ldap_search_base_dn"; + public static final String ldapSearchFilter = "ldap_search_filter"; + + public static boolean propertiesValid() { + if (Globals.properties.getProperty(ftpBaseDir).isEmpty() + || Globals.properties.getProperty(imageDir).isEmpty() + || Globals.properties.getProperty(ldapPort).isEmpty() + || Globals.properties.getProperty(ldapHost).isEmpty() + || Globals.properties.getProperty(ldapSsl).isEmpty() + || Globals.properties.getProperty(ldapBindQuery).isEmpty() + || Globals.properties.getProperty(ldapSearchBaseDn).isEmpty() + || Globals.properties.getProperty(ldapSearchBaseDn).isEmpty() + ) { + return false; + } + + if (StringUtils.countMatches(Globals.properties.getProperty(ldapBindQuery), "%") != 1) { + return false; + } + + if (StringUtils.countMatches(Globals.properties.getProperty(ldapSearchFilter), "%") != 1) { + return false; + } + + // remove "/" at the end of the path + String ftp = Globals.properties.getProperty(ftpBaseDir); + if (ftp.endsWith("/")) { + Globals.properties.put(ftpBaseDir, ftp.substring(0, ftp.length() - 1)); + } + + String image = Globals.properties.getProperty(imageDir); + if (image.endsWith("/")) { + Globals.properties.put(imageDir, image.substring(0, image.length() -1 )); + } + + return true; + } } diff --git a/src/main/java/org/openslx/imagemaster/db/ImageProcessor.java b/src/main/java/org/openslx/imagemaster/db/ImageProcessor.java index d43b507..8c8bd8c 100644 --- a/src/main/java/org/openslx/imagemaster/db/ImageProcessor.java +++ b/src/main/java/org/openslx/imagemaster/db/ImageProcessor.java @@ -12,10 +12,18 @@ public class ImageProcessor { private static Logger log = Logger.getLogger(ImageProcessor.class); private static HashMap<String, ImageData> images = new HashMap<>(); - public static void processImageAfterUpload(String username, String filename) { - /* - * TODO: Process the image after download - */ + + /** + * 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 + "'"); @@ -27,7 +35,7 @@ public class ImageProcessor { if (!imageFile.exists()) { // image file does not exist - return; + return false; } imageFile.renameTo( new File(newFileName) ); @@ -40,6 +48,9 @@ public class ImageProcessor { // update database DbImage.update(images.get(username), newFileName); log.info("Updated db: " + images.get(username).uuid); + + images.remove(username); + return true; } /** diff --git a/src/main/java/org/openslx/imagemaster/db/LdapUser.java b/src/main/java/org/openslx/imagemaster/db/LdapUser.java index 17bf65e..1124696 100644 --- a/src/main/java/org/openslx/imagemaster/db/LdapUser.java +++ b/src/main/java/org/openslx/imagemaster/db/LdapUser.java @@ -14,6 +14,7 @@ import org.apache.directory.api.ldap.model.message.SearchScope; import org.apache.directory.ldap.client.api.LdapConnectionConfig; import org.apache.directory.ldap.client.api.LdapNetworkConnection; import org.apache.log4j.Logger; +import org.openslx.imagemaster.Globals; import org.openslx.imagemaster.session.User; import org.openslx.imagemaster.thrift.iface.AuthenticationError; import org.openslx.imagemaster.thrift.iface.AuthenticationException; @@ -63,24 +64,27 @@ public class LdapUser extends User * @param login Login of user in the form "user@organization.com" * @return instance of LDAPUser for matching entry from LDAP, or null if not found */ - @SuppressWarnings("finally") public static LdapUser forLogin( final String login, final String password ) throws AuthenticationException { - String username, organization, firstName, lastName, eMail, satelliteAddress; + String username, organization, firstName, lastName, eMail, satelliteAddress; + + String[] temp = login.split("@"); + if (temp.length != 2) throw new AuthenticationException( AuthenticationError.GENERIC_ERROR, "Login must be in form user@organization.com"); + username = temp[0]; - // TODO: Read connection info from config file LdapConnectionConfig ldapConfig = new LdapConnectionConfig(); ldapConfig.setTrustManagers(new MyTrustManager()); - ldapConfig.setLdapPort(636); - ldapConfig.setLdapHost("bv1.ruf.uni-freiburg.de"); - ldapConfig.setUseSsl(true); + ldapConfig.setLdapPort(Integer.valueOf(Globals.properties.getProperty(Globals.ldapPort))); + ldapConfig.setLdapHost(Globals.properties.getProperty(Globals.ldapHost)); + ldapConfig.setUseSsl(Boolean.valueOf(Globals.properties.getProperty(Globals.ldapSsl))); LdapNetworkConnection connection = new LdapNetworkConnection( ldapConfig ); // bind connection - // TODO: Hard coded stuff here too. binddn, search query etc. need to be configurable try { - if ( connection.connect() ) - connection.bind("uid=" + login + ",ou=people,dc=uni-freiburg,dc=de", password); + if ( connection.connect() ) { + String name = Globals.properties.getProperty(Globals.ldapBindQuery).replace("%", username); + connection.bind(name, password); + } } catch (LdapException e1) { log.warn( "Connection to LDAP failed: " + e1.getMessage() ); } @@ -108,8 +112,8 @@ public class LdapUser extends User // make search query try { - EntryCursor cursor = connection.search("ou=people,dc=uni-freiburg,dc=de", "(&(objectclass=person)(uid=" - + login + "))", SearchScope.SUBTREE); + EntryCursor cursor = connection.search(Globals.properties.getProperty(Globals.ldapSearchBaseDn), + Globals.properties.getProperty(Globals.ldapSearchFilter).replace("%", username), SearchScope.SUBTREE); // only use the first result cursor.next(); Entry entry = cursor.get(); diff --git a/src/main/java/org/openslx/imagemaster/server/ApiServer.java b/src/main/java/org/openslx/imagemaster/server/ApiServer.java index eda48eb..fc1d9b0 100644 --- a/src/main/java/org/openslx/imagemaster/server/ApiServer.java +++ b/src/main/java/org/openslx/imagemaster/server/ApiServer.java @@ -1,7 +1,9 @@ package org.openslx.imagemaster.server; import java.io.File; +import java.util.HashMap; +import org.apache.ftpserver.ftplet.FtpException; import org.apache.log4j.Logger; import org.apache.thrift.TException; import org.openslx.imagemaster.Globals; @@ -17,10 +19,13 @@ import org.openslx.imagemaster.session.SessionManager; import org.openslx.imagemaster.session.User; import org.openslx.imagemaster.thrift.iface.AuthenticationError; import org.openslx.imagemaster.thrift.iface.AuthenticationException; +import org.openslx.imagemaster.thrift.iface.AuthorizationError; import org.openslx.imagemaster.thrift.iface.AuthorizationException; import org.openslx.imagemaster.thrift.iface.FtpCredentials; import org.openslx.imagemaster.thrift.iface.ImageData; import org.openslx.imagemaster.thrift.iface.InvalidTokenException; +import org.openslx.imagemaster.thrift.iface.ServerAuthenticationError; +import org.openslx.imagemaster.thrift.iface.ServerAuthenticationException; import org.openslx.imagemaster.thrift.iface.ServerSessionData; import org.openslx.imagemaster.thrift.iface.SessionData; import org.openslx.imagemaster.thrift.iface.UserInfo; @@ -85,29 +90,22 @@ public class ApiServer { * @throws AuthorizationException if the uni/hs server has no valid session * @throws TException */ - public static FtpCredentials submitImage(ImageData imageDescription, - ServerSessionData serverSessionData) throws AuthorizationException, + public static FtpCredentials submitImage(String serverSessionId, + ImageData imageDescription) throws AuthorizationException, TException { - if (ServerSessionManager.getSession(serverSessionData.sessionId) == null) { - throw new AuthenticationException(AuthenticationError.GENERIC_ERROR, "No valid serverSessionData"); + if (ServerSessionManager.getSession(serverSessionId) == null) { + throw new AuthorizationException(AuthorizationError.NOT_AUTHENTICATED, "No valid serverSessionData"); } - String generatedUser = RandomString.generate(10, false); - String generatedPass = RandomString.generate(16, true); + // create new user + FtpCredentials ftpCredentials = Globals.ftpServer.addUser(serverSessionId); - if (!ImageProcessor.addImageDataToProcess(imageDescription, generatedUser)) { + if (!ImageProcessor.addImageDataToProcess(imageDescription, ftpCredentials.username)) { + Globals.ftpServer.removeUser(serverSessionId); throw new TException("ImageData is not valid."); } - - String dir = Globals.properties.getProperty("ftp_base_dir") + "/" - + generatedUser + "/"; - if (new File(dir).mkdir()) { - Globals.ftpServer.addUser(generatedUser, generatedPass, dir, true); - log.info("Generated user/pass: " + generatedUser + "\t" - + generatedPass + "\n with home dir: " + dir); - } - - return new FtpCredentials(generatedUser, generatedPass); + + return ftpCredentials; } /** @@ -115,16 +113,15 @@ public class ApiServer { * @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 - * @throws TException + * @throws ServerAuthenticationException when organization is invalid/unknown */ public static String startServerAuthentication(String organization) - throws TException { - // TODO: Proper exceptions + throws ServerAuthenticationException { if (organization == null || organization == "") { - throw new TException("Empty organization"); + throw new ServerAuthenticationException(ServerAuthenticationError.INVALID_ORGANIZATION, "Empty organization"); } if (DbSatellite.fromOrganization(organization) == null) { - throw new TException("Unkown organization"); + throw new ServerAuthenticationException(ServerAuthenticationError.INVALID_ORGANIZATION, "Unknown organization"); } return ServerAuthenticator.startServerAuthentication(organization); } @@ -140,13 +137,12 @@ public class ApiServer { public static ServerSessionData serverAuthenticate(String organization, String challengeResponse) throws AuthenticationException, TException { - // TODO: Proper exceptions if (organization == null || challengeResponse == null) { - throw new TException("Empty organization org challengeResponse"); + throw new ServerAuthenticationException(ServerAuthenticationError.INVALID_ORGANIZATION, "Empty organization or challengeResponse"); } DbSatellite satellite = DbSatellite.fromOrganization(organization); if (satellite == null) { - throw new TException("Unkown organization"); + throw new ServerAuthenticationException(ServerAuthenticationError.INVALID_ORGANIZATION, "Unknown organization"); } final ServerUser serverUser = ServerAuthenticator.serverAuthenticate( organization, satellite.getAddress(), challengeResponse); @@ -155,4 +151,39 @@ public class ApiServer { 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 { + // check if valid session exists + 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); + File[] list = userDirectory.listFiles(); + + 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); + + return true; + } + } diff --git a/src/main/java/org/openslx/imagemaster/server/MasterFtpServer.java b/src/main/java/org/openslx/imagemaster/server/MasterFtpServer.java index 973c768..c6592bc 100644 --- a/src/main/java/org/openslx/imagemaster/server/MasterFtpServer.java +++ b/src/main/java/org/openslx/imagemaster/server/MasterFtpServer.java @@ -17,11 +17,15 @@ 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.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; + private HashMap<String, FtpCredentials> users = new HashMap<>(); public MasterFtpServer(int port, String adminUsername, String adminPassword, String ftproot) { FtpServerFactory serverFactory = new FtpServerFactory(); @@ -39,7 +43,7 @@ public class MasterFtpServer implements Runnable { userManager = userManagerFactory.createUserManager(); // create new admin user - addUser(adminUsername, adminPassword, ftproot, true); + //addUser(adminUsername, adminPassword, ftproot, true); serverFactory.setUserManager(userManager); // add the Ftplet @@ -51,38 +55,57 @@ public class MasterFtpServer implements Runnable { server = serverFactory.createServer(); } - public boolean addUser(final String username, final String password, final String ftproot, final boolean writeAccess) { + public FtpCredentials addUser(final String serverSessionId) { // TODO: enable SSL - boolean result = true; + + FtpCredentials ftpCredentials = null; + + String generatedUser = RandomString.generate(10, false); + String generatedPass = RandomString.generate(16, true); + + String dir = Globals.properties.getProperty(Globals.ftpBaseDir) + "/" + + generatedUser + "/"; + + if (!new File(dir).mkdir()) { + return ftpCredentials; + } BaseUser user = new BaseUser(); - user.setName(username); - user.setPassword(password); - user.setHomeDirectory(ftproot); + user.setName(generatedUser); + user.setPassword(generatedPass); + user.setHomeDirectory(dir); List<Authority> authorities = new ArrayList<Authority>(); - if (writeAccess) authorities.add(new WritePermission()); + authorities.add(new WritePermission()); user.setAuthorities(authorities); try { userManager.save(user); + ftpCredentials = new FtpCredentials(generatedUser, generatedPass); + users.put(serverSessionId, ftpCredentials); } catch (FtpException e) { - result = false; } - return result; + log.info("Generated user/pass: " + generatedUser + "\t" + + generatedPass + "\n with home dir: " + dir); + + return ftpCredentials; } - public boolean removeUser(final String username) { - boolean result = true; + public boolean removeUser(final String serverSessionId) { + if (!users.containsKey(serverSessionId)) return false; try { - userManager.delete(username); + userManager.delete(users.get(serverSessionId).username); + users.remove(serverSessionId); + return true; } catch (FtpException e) { - result = false; + return false; } - - return result; + } + + public FtpCredentials getCredentialsFromSessionId(String serverSessionId) { + return users.get(serverSessionId); } @Override 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 096f63f..899af1a 100644 --- a/src/main/java/org/openslx/imagemaster/thrift/server/ImageServerHandler.java +++ b/src/main/java/org/openslx/imagemaster/thrift/server/ImageServerHandler.java @@ -53,10 +53,16 @@ public class ImageServerHandler implements ImageServer.Iface } @Override - public FtpCredentials submitImage(ImageData imageDescription, - ServerSessionData serverSessionData) throws AuthorizationException, + public FtpCredentials submitImage(String serverSessionId, + ImageData imageDescription) throws AuthorizationException, TException { - return ApiServer.submitImage(imageDescription, serverSessionData); + return ApiServer.submitImage(serverSessionId, imageDescription); + } + + @Override + public boolean finshedUpload(String serverSessionId, + ImageData imageDescription) throws AuthorizationException { + return ApiServer.finishedUpload(serverSessionId, imageDescription); } } diff --git a/src/main/thrift/imagemaster.thrift b/src/main/thrift/imagemaster.thrift index a164e9b..fdf63ee 100644 --- a/src/main/thrift/imagemaster.thrift +++ b/src/main/thrift/imagemaster.thrift @@ -23,6 +23,12 @@ enum AuthenticationError { BANNED_NETWORK } +enum ServerAuthenticationError { + GENERIC_ERROR, + INVALID_ORGANIZATION, + BANNED_NETWORK, +} + exception AuthorizationException { 1: AuthorizationError number, 2: string message @@ -36,6 +42,11 @@ exception AuthenticationException { exception InvalidTokenException { } +exception ServerAuthenticationException { + 1: ServerAuthenticationError number, + 2: string message +} + struct UserInfo { 1: string userId, 2: string firstName, @@ -82,9 +93,11 @@ service ImageServer { string startServerAuthentication(1:string organization), - ServerSessionData serverAuthenticate(1:string organization, 2:string challengeResponse) throws (1:AuthenticationException failure), + ServerSessionData serverAuthenticate(1:string organization, 2:string challengeResponse) throws (1:ServerAuthenticationException failure), + + FtpCredentials submitImage(1:string serverSessionId, 2:ImageData imageDescription) throws (1:AuthorizationException failure), - FtpCredentials submitImage(1:ImageData imageDescription, 2:ServerSessionData serverSessionData) throws (1:AuthorizationException failure) + bool finshedUpload(1:string serverSessionId, 2:ImageData imageDescription) throws (1:AuthorizationException failure) } diff --git a/src/test/java/org/openslx/imagemaster/AppTest.java b/src/test/java/org/openslx/imagemaster/AppTest.java index 120bd9e..a491242 100644 --- a/src/test/java/org/openslx/imagemaster/AppTest.java +++ b/src/test/java/org/openslx/imagemaster/AppTest.java @@ -122,7 +122,7 @@ public class AppTest System.out.println("Created imageData"); - FtpCredentials ftpCredentials = client.submitImage(imageData, data); + FtpCredentials ftpCredentials = client.submitImage(data.sessionId, imageData); System.out.println("Got FTP credentials. User: " + ftpCredentials.username + ", password: " + ftpCredentials.password); FTPClient FtpClient = new FTPClient(); |
