diff options
author | Nils Schwabe | 2014-04-10 11:58:34 +0200 |
---|---|---|
committer | Nils Schwabe | 2014-04-10 11:58:34 +0200 |
commit | d5e1e558f22de9e20fbee6c1e8a884e65fa7cbbc (patch) | |
tree | c9895bd99ed579d421343b41e9611da23eb1a4c1 | |
parent | added new thrift methods: (diff) | |
download | masterserver-d5e1e558f22de9e20fbee6c1e8a884e65fa7cbbc.tar.gz masterserver-d5e1e558f22de9e20fbee6c1e8a884e65fa7cbbc.tar.xz masterserver-d5e1e558f22de9e20fbee6c1e8a884e65fa7cbbc.zip |
Added authentification for uni/hs server
--> added serversession, serversessionmanager
--> missing implementation for server authentication
10 files changed, 295 insertions, 64 deletions
diff --git a/src/main/java/org/openslx/imagemaster/App.java b/src/main/java/org/openslx/imagemaster/App.java index 62e06a4..3a309c5 100644 --- a/src/main/java/org/openslx/imagemaster/App.java +++ b/src/main/java/org/openslx/imagemaster/App.java @@ -1,15 +1,12 @@ package org.openslx.imagemaster; import java.io.BufferedInputStream; -import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import java.security.SecureRandom; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; -import org.openslx.imagemaster.server.MasterFtpServer; import org.openslx.imagemaster.thrift.server.BinaryListener; public class App { @@ -51,39 +48,10 @@ public class App { // Create Ftp Server Thread f; - MasterFtpServer ftpServer = new MasterFtpServer(2221, "admin", - "SI*HoZCC!]V)p>B2", Globals.properties.getProperty("ftp_base_dir")); - f = new Thread(ftpServer, "FtpServer"); + f = new Thread(Globals.ftpServer, "FtpServer"); servers.add(f); f.start(); - /* - * FTP Users can be added later with: - * ftpServer.addUser(username, password, ftp_root); - * - * And removed with: - * removeUser(username); - */ - - //////////////////////////////////////////////// - SecureRandom random = new SecureRandom(); - String lettersP="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890+-$%&/()=?@"; - String lettersU="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; - String generatedUser = ""; - String generatedPass = ""; - for (int i = 0; i < 16; i++) { - int index = (int)(random.nextDouble()*lettersU.length()); - generatedUser += lettersU.substring(index, index + 1); - index = (int)(random.nextDouble()*lettersP.length()); - generatedPass += lettersP.substring(index, index + 1); - } - String dir = Globals.properties.getProperty("ftp_base_dir") + "/" + generatedUser + "/"; - if (new File(dir).mkdir()) { - ftpServer.addUser(generatedUser, generatedPass, dir, true); - log.info("Generated user/pass: " + generatedUser + "\t" + generatedPass + "\n with home dir: " + dir); - } - //////////////////////////////////////////////// - // Run more servers // ... // Wait for all servers to die @@ -99,8 +67,6 @@ public class App { } } - ftpServer.removeUser(generatedUser); - log.info("All Servers shut down, exiting..."); } } diff --git a/src/main/java/org/openslx/imagemaster/Globals.java b/src/main/java/org/openslx/imagemaster/Globals.java index 0cca10d..b766b27 100644 --- a/src/main/java/org/openslx/imagemaster/Globals.java +++ b/src/main/java/org/openslx/imagemaster/Globals.java @@ -2,6 +2,10 @@ package org.openslx.imagemaster; import java.util.Properties; +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")); } diff --git a/src/main/java/org/openslx/imagemaster/server/ApiServer.java b/src/main/java/org/openslx/imagemaster/server/ApiServer.java index ba15623..3799079 100644 --- a/src/main/java/org/openslx/imagemaster/server/ApiServer.java +++ b/src/main/java/org/openslx/imagemaster/server/ApiServer.java @@ -1,15 +1,29 @@ package org.openslx.imagemaster.server; +import java.io.File; + import org.apache.log4j.Logger; +import org.apache.thrift.TException; +import org.openslx.imagemaster.Globals; +import org.openslx.imagemaster.db.DbSatellite; +import org.openslx.imagemaster.serversession.ServerAuthenticator; +import org.openslx.imagemaster.serversession.ServerSession; +import org.openslx.imagemaster.serversession.ServerSessionManager; +import org.openslx.imagemaster.serversession.ServerUser; import org.openslx.imagemaster.session.Authenticator; import org.openslx.imagemaster.session.Session; 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.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.ServerSessionData; import org.openslx.imagemaster.thrift.iface.SessionData; import org.openslx.imagemaster.thrift.iface.UserInfo; +import org.openslx.imagemaster.util.RandomString; /** * API Server This is where all the requests from the outside arrive. We don't @@ -22,42 +36,106 @@ 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 -{ - @SuppressWarnings( "unused" ) - private static Logger log = Logger.getLogger( ApiServer.class ); +public class ApiServer { + private static Logger log = Logger.getLogger(ApiServer.class); /** * Request for authentication - * @param login (username@organization) + * + * @param login + * (username@organization) * @param password * @return SessionData struct with session id/token iff login successful - * @throws AuthenticationException if login not successful + * @throws AuthenticationException + * if login not successful */ - public static SessionData authenticate( String login, String password ) + 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!" ); + if (login == null || password == null) { + throw new AuthenticationException( + AuthenticationError.INVALID_CREDENTIALS, + "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); } /** * Request information about user for given token - * @param token - a user's token + * + * @param token + * - a user's token * @return UserInfo struct for given token's user - * @throws InvalidTokenException if no user matches the given token + * @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()); + } + + public static FtpCredentials submitImage(ImageData imageDescription, + ServerSessionData serverSessionData) throws AuthorizationException, + TException { + /* + * TODO: + * Check if session is ok. + * create and return FtpCredentials + */ + + /* + * FTP Users can be added later with: ftpServer.addUser(username, + * password, ftp_root); + * + * And removed with: removeUser(username); + */ + + String generatedUser = RandomString.generate(10, false); + String generatedPass = RandomString.generate(16, true); + 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); + } + // TODO: remove old user + + return new FtpCredentials(generatedUser, generatedPass); + } + + public static String startServerAuthentication(String organization) + throws TException { + if (organization == null || organization == "") { + throw new TException("Empty organization"); + } + if (DbSatellite.fromOrganization(organization) == null) { + throw new TException("Unkown organization"); + } + return ServerAuthenticator.startServerAuthentication(organization); + } + + public static ServerSessionData serverAuthenticate(String organization, + String challengeResponse) throws AuthenticationException, + TException { + if (organization == null || challengeResponse == null) { + throw new TException("Empty organization org challengeResponse"); + } + DbSatellite satellite = DbSatellite.fromOrganization(organization); + if (satellite == null) { + throw new TException("Unkown organization"); + } + final ServerUser serverUser = ServerAuthenticator.serverAuthenticate( + organization, satellite.getAddress(), challengeResponse); + + final ServerSession session = new ServerSession(serverUser); + return ServerSessionManager.addSession(session); } } diff --git a/src/main/java/org/openslx/imagemaster/serversession/ServerAuthenticator.java b/src/main/java/org/openslx/imagemaster/serversession/ServerAuthenticator.java new file mode 100644 index 0000000..b16766a --- /dev/null +++ b/src/main/java/org/openslx/imagemaster/serversession/ServerAuthenticator.java @@ -0,0 +1,40 @@ +package org.openslx.imagemaster.serversession; + +import java.util.HashMap; + +import org.apache.thrift.TException; +import org.openslx.imagemaster.thrift.iface.AuthenticationException; +import org.openslx.imagemaster.util.RandomString; + +public class ServerAuthenticator { + private static HashMap<String, String> authenticatingServers = new HashMap<String, String>(); + /** + * Start the server authentification. + * @param organization the organization of the server + * @return encrypted random string + */ + public static String startServerAuthentication(String organization) { + /* + * TODO: + * Create random string, send it to server. + * Remember organization for later authentification. + */ + String secret = RandomString.generate(100, false); + synchronized (authenticatingServers) { + authenticatingServers.put(organization, secret); + } + return secret; + } + + + public static ServerUser serverAuthenticate(String organization, String address, + String challengeResponse) throws AuthenticationException, + TException { + /* + * TODO: + * Decrypt the given challengeResponse and check whether it was right or not. + * Authenticate server if so. + */ + return new ServerUser(organization, address); + } +} diff --git a/src/main/java/org/openslx/imagemaster/serversession/ServerSession.java b/src/main/java/org/openslx/imagemaster/serversession/ServerSession.java new file mode 100644 index 0000000..e15f863 --- /dev/null +++ b/src/main/java/org/openslx/imagemaster/serversession/ServerSession.java @@ -0,0 +1,35 @@ +package org.openslx.imagemaster.serversession; + +public class ServerSession { + + private static final long TIMEOUT = 600L * 1000L; // TODO: config + + private long timeOut = 0; + private final ServerUser serverUser; + + public ServerSession(final ServerUser serverUser) + { + this.serverUser = serverUser; + this.timeOut = System.currentTimeMillis() + TIMEOUT; + } + + public synchronized void refresh() + { + if ( timedOut() ) + return; // Don't allow refreshing timed out session + this.timeOut = System.currentTimeMillis() + TIMEOUT; + } + + public synchronized boolean timedOut() + { + return System.currentTimeMillis() > this.timeOut; + } + + public String getOrganization() { + return serverUser.organization; + } + + public String getAddress() { + return serverUser.address; + } +} diff --git a/src/main/java/org/openslx/imagemaster/serversession/ServerSessionManager.java b/src/main/java/org/openslx/imagemaster/serversession/ServerSessionManager.java new file mode 100644 index 0000000..1fd4322 --- /dev/null +++ b/src/main/java/org/openslx/imagemaster/serversession/ServerSessionManager.java @@ -0,0 +1,69 @@ +package org.openslx.imagemaster.serversession; + +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.UUID; + +import org.apache.log4j.Logger; +import org.openslx.imagemaster.session.SessionManager; +import org.openslx.imagemaster.thrift.iface.ServerSessionData; +import org.openslx.imagemaster.util.Hash; + +public class ServerSessionManager { + + private static Logger log = Logger.getLogger( SessionManager.class ); + + // Map of currently known sessions + private static final Map<String, ServerSession> serverSessions = new LinkedHashMap<String, ServerSession>(); + private static final Thread gcThread; + + public static ServerSessionData addSession( ServerSession serverSession ) + { + final String sessionId = Hash.sha256( UUID.randomUUID().toString() ); + + synchronized ( serverSessions ) { + serverSessions.put( sessionId, serverSession ); + } + return new ServerSessionData( sessionId ); + } + + public static ServerSession getSession( String sessionId ) + { + final ServerSession serverSession; + synchronized ( serverSessions ) { + serverSession = serverSessions.get( sessionId ); + } + if ( serverSession == null || serverSession.timedOut() ) { + return null; + } + return serverSession; + } + + static { + gcThread = new Thread( new Runnable() { + @Override + public void run() + { + for ( ;; ) { + try { + Thread.sleep( 1800L * 1000L ); + } catch ( InterruptedException e ) { + } + synchronized ( serverSessions ) { + Iterator<ServerSession> it = serverSessions.values().iterator(); + while ( it.hasNext() ) { + final ServerSession s = it.next(); + if ( s.timedOut() ) { + log.debug( "Removing old session of " + s.getOrganization() ); + it.remove(); + } + } + } + } + } + } ); + gcThread.start(); + } + +} diff --git a/src/main/java/org/openslx/imagemaster/serversession/ServerUser.java b/src/main/java/org/openslx/imagemaster/serversession/ServerUser.java new file mode 100644 index 0000000..48815a8 --- /dev/null +++ b/src/main/java/org/openslx/imagemaster/serversession/ServerUser.java @@ -0,0 +1,11 @@ +package org.openslx.imagemaster.serversession; + +public class ServerUser { + public final String organization, address; + + public ServerUser(String organization, String address) { + this.organization = organization; + this.address = address; + } + +} 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 dc1b8f1..858f682 100644 --- a/src/main/java/org/openslx/imagemaster/thrift/server/ImageServerHandler.java +++ b/src/main/java/org/openslx/imagemaster/thrift/server/ImageServerHandler.java @@ -42,23 +42,21 @@ public class ImageServerHandler implements ImageServer.Iface @Override public String startServerAuthentication(String organization) throws TException { - // TODO Auto-generated method stub - return null; + return ApiServer.startServerAuthentication(organization); } @Override public ServerSessionData serverAuthenticate(String organization, String challengeResponse) throws AuthenticationException, TException { - // TODO Auto-generated method stub - return null; + return ApiServer.serverAuthenticate(organization, challengeResponse); } @Override - public FtpCredentials submitImage(ImageData imageDescription) - throws AuthorizationException, TException { - // TODO Auto-generated method stub - return null; + public FtpCredentials submitImage(ImageData imageDescription, + ServerSessionData serverSessionData) throws AuthorizationException, + TException { + return ApiServer.submitImage(imageDescription, serverSessionData); } } diff --git a/src/main/java/org/openslx/imagemaster/util/RandomString.java b/src/main/java/org/openslx/imagemaster/util/RandomString.java new file mode 100644 index 0000000..a0e9419 --- /dev/null +++ b/src/main/java/org/openslx/imagemaster/util/RandomString.java @@ -0,0 +1,30 @@ +package org.openslx.imagemaster.util; + +import java.security.SecureRandom; + +/** + * Generate secure random strings + * @author nils + * + */ +public class RandomString { + private static final String lettersSpecial="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890+-$%&/()=?@"; + private static final String letters="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; + private static final SecureRandom random = new SecureRandom(); + + /** + * Generate a random string. + * @param length the length of the string + * @param specialChars whether to use special charachters or not + * @return the generated string + */ + public static String generate(int length, boolean specialChars) { + String used = (specialChars)? lettersSpecial : letters; + String result = ""; + for (int i = 0; i < length; i++) { + int index = (int)(random.nextDouble()*used.length()); + result += used.substring( index, index + 1 ); + } + return result; + } +} diff --git a/src/main/thrift/imagemaster.thrift b/src/main/thrift/imagemaster.thrift index 7f50dfc..8a4afcf 100644 --- a/src/main/thrift/imagemaster.thrift +++ b/src/main/thrift/imagemaster.thrift @@ -75,7 +75,7 @@ service ImageServer { ServerSessionData serverAuthenticate(1:string organization, 2:string challengeResponse) throws (1:AuthenticationException failure), - FtpCredentials submitImage(1:ImageData imageDescription) throws (1:AuthorizationException failure) + FtpCredentials submitImage(1:ImageData imageDescription, 2:ServerSessionData serverSessionData) throws (1:AuthorizationException failure) } |