diff --git a/guacamole-tunnel/README.txt b/guacamole-tunnel/README.txt new file mode 100644 index 00000000..c5c47e2f --- /dev/null +++ b/guacamole-tunnel/README.txt @@ -0,0 +1,5 @@ +In order to increase the security of the server, there will be a key, stored at /etc/uniqueid.cfg, that will be required in order to store +valid credentials for users. + +The credentials for the user are 1 time used, so if connection is lost, there will be needed a full register-cred, connect to acces again to session. + diff --git a/guacamole-tunnel/src/main/java/org/openuds/guacamole/CredentialsServlet.java b/guacamole-tunnel/src/main/java/org/openuds/guacamole/CredentialsServlet.java new file mode 100644 index 00000000..47c7f1cf --- /dev/null +++ b/guacamole-tunnel/src/main/java/org/openuds/guacamole/CredentialsServlet.java @@ -0,0 +1,67 @@ +package org.openuds.guacamole; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.PrintWriter; +import org.openuds.guacamole.creds.Credentials; + +public class CredentialsServlet extends HttpServlet { + + /** + * + */ + private static final long serialVersionUID = 8321644141165009209L; + private static final String UUID_ERROR = "ERROR: Invalid UUID"; + private static final String PARAMS_ERROR = "ERROR: Invalid Credentials Parameters"; + private static final String OK = "OK"; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + processCredentials(req, resp); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + processCredentials(req, resp); + } + + private void processCredentials(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + + resp.setContentType("text/plain"); + PrintWriter out = resp.getWriter(); + + String uuid = req.getParameter("uuid"); + String cred = req.getParameter("credential"); + String data = req.getParameter("data"); + + if( req.getParameter("test") != null && uuid != null ) { + if( Credentials.test(uuid) == false ) + out.println(UUID_ERROR); + else + out.println(OK); + return; + } + + if( uuid == null || cred == null || data == null ) { + out.println(PARAMS_ERROR); + return; + } + + // Test url: + // /creds?uuid=f070f721-15ea-44a9-8df1-b9480991989c&credential=12345&data=protocol%09rdp%0ahostname%09w7adolfo%0ausername%09admin%0apassword%09temporal + + if( Credentials.put(uuid, cred, data) == false ) + out.println(UUID_ERROR); + else + out.println(OK); + + } + +} diff --git a/guacamole-tunnel/src/main/java/org/openuds/guacamole/TunnelServlet.java b/guacamole-tunnel/src/main/java/org/openuds/guacamole/TunnelServlet.java index 128d9e71..a0d7c669 100644 --- a/guacamole-tunnel/src/main/java/org/openuds/guacamole/TunnelServlet.java +++ b/guacamole-tunnel/src/main/java/org/openuds/guacamole/TunnelServlet.java @@ -34,25 +34,13 @@ public class TunnelServlet if( data == null || width == null || height == null) throw new GuacamoleException("Can't read required parameters"); - HttpSession rSession = request.getSession(); - - @SuppressWarnings("unchecked") - Hashtable params = (Hashtable)rSession.getAttribute(data); + Hashtable params = Util.readParameters(data); + if( params == null ) { + System.out.println("Invalid credentials"); + throw new GuacamoleException("Can't access required user credentials"); + } - // Parameters not owned by user session, get them from remote server - // (one time shot at other side, so they can't be retrieved again) - if( params == null ) { - try { - params = Util.readParameters(data); - rSession.setAttribute(data, params); - } catch(Exception e) { - throw new GuacamoleException("Getting broker data", e); - } - } - else - System.out.println("Params got from session"); - GuacamoleClientInformation info = new GuacamoleClientInformation(); info.setOptimalScreenWidth(Integer.parseInt(width)); info.setOptimalScreenHeight(Integer.parseInt(height)); diff --git a/guacamole-tunnel/src/main/java/org/openuds/guacamole/Util.java b/guacamole-tunnel/src/main/java/org/openuds/guacamole/Util.java index 48f3ce78..f3ae9e98 100644 --- a/guacamole-tunnel/src/main/java/org/openuds/guacamole/Util.java +++ b/guacamole-tunnel/src/main/java/org/openuds/guacamole/Util.java @@ -1,16 +1,19 @@ package org.openuds.guacamole; -import java.io.BufferedReader; -import java.io.InputStreamReader; import java.util.Hashtable; +import org.openuds.guacamole.creds.Credentials; public class Util { + // public static Hashtable readParameters(String data) { //String url = unscramble(data); //String params = getUrl(url); //return parseParams(params); - return parseParams("protocol\trdp\nhostname\tw7adolfo\nusername\tadmin\npassword\ttemporal"); + String params = Credentials.getAndRemove(data); + if( params == null ) + return null; + return parseParams(params); } public static Hashtable parseParams(String params) @@ -27,41 +30,4 @@ public class Util { return res; } - public static String unscramble(String in) - { - int len = in.length(); - StringBuilder res = new StringBuilder(len/2); - int val = 0x32; - for( int i = 0; i < len; i += 2) { - String b = in.substring(i, i+2); - int c = Integer.parseInt(b, 16)^val; - val = (val + c) & 0xFF; - res.append((char)c); - } - - return res.reverse().toString(); - } - - - public static String getUrl(String url) { - try { - java.net.URL u = new java.net.URL(url); - BufferedReader in = new BufferedReader(new InputStreamReader(u.openStream())); - StringBuilder data = new StringBuilder(); - - String inputLine; - while ((inputLine = in.readLine()) != null) { - data.append(inputLine); - data.append("\n"); - } - - in.close(); - return data.toString(); - - } catch(Exception e) { - System.out.println("Unable to get url. Network error? " + e.getMessage()); - return null; - } - - } } \ No newline at end of file diff --git a/guacamole-tunnel/src/main/java/org/openuds/guacamole/creds/Credentials.java b/guacamole-tunnel/src/main/java/org/openuds/guacamole/creds/Credentials.java new file mode 100644 index 00000000..887be276 --- /dev/null +++ b/guacamole-tunnel/src/main/java/org/openuds/guacamole/creds/Credentials.java @@ -0,0 +1,45 @@ +package org.openuds.guacamole.creds; + +import java.util.LinkedHashMap; + +public class Credentials { + + private static CredentialsMap creds = new CredentialsMap(); + + public static boolean put(String uuid, String credential, String value) { + synchronized (creds) { + if( uuid.equals(creds.uniqueId) ) { + creds.put(credential, value); + return true; + } + return false; + } + } + + public static String get(String credential) { + synchronized (creds) { + return creds.get(credential); + } + } + + public static String getAndRemove(String credential) { + synchronized (creds) { + String cred = creds.get(credential); + creds.put(credential, null); + return cred; + + } + } + + public static boolean test(String uuid) { + synchronized (creds) { + if( uuid.equals(creds.uniqueId) ) + return true; + return false; + } + + } + + +} + diff --git a/guacamole-tunnel/src/main/java/org/openuds/guacamole/creds/CredentialsMap.java b/guacamole-tunnel/src/main/java/org/openuds/guacamole/creds/CredentialsMap.java new file mode 100644 index 00000000..81e8d1d9 --- /dev/null +++ b/guacamole-tunnel/src/main/java/org/openuds/guacamole/creds/CredentialsMap.java @@ -0,0 +1,32 @@ +package org.openuds.guacamole.creds; + +import java.io.BufferedReader; +import java.io.DataInputStream; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.util.LinkedHashMap; + +public class CredentialsMap extends LinkedHashMap { + + private static final int MAX_CREDENTIALS = 1024; + public String uniqueId; + + public CredentialsMap() { + super(MAX_CREDENTIALS); + try { + FileInputStream fi = new FileInputStream("/etc/uniqueid.cfg"); + DataInputStream in = new DataInputStream(fi); + BufferedReader br = new BufferedReader(new InputStreamReader(in)); + uniqueId = br.readLine(); + in.close(); + } catch(Exception e) { + uniqueId = null; + } + } + + @Override + protected boolean removeEldestEntry( + java.util.Map.Entry eldest) { + return size() >= MAX_CREDENTIALS; + } +} diff --git a/guacamole-tunnel/src/main/webapp/WEB-INF/web.xml b/guacamole-tunnel/src/main/webapp/WEB-INF/web.xml index 7dcb4f99..c5e05b0a 100644 --- a/guacamole-tunnel/src/main/webapp/WEB-INF/web.xml +++ b/guacamole-tunnel/src/main/webapp/WEB-INF/web.xml @@ -20,9 +20,22 @@ + + Credentials Servlet + Credentials + + org.openuds.guacamole.CredentialsServlet + + + Tunnel /tunnel + + Credentials + /creds + + diff --git a/guacamole-tunnel/src/main/webapp/index.xhtml b/guacamole-tunnel/src/main/webapp/index.xhtml index 8083cdc1..95d1330d 100644 --- a/guacamole-tunnel/src/main/webapp/index.xhtml +++ b/guacamole-tunnel/src/main/webapp/index.xhtml @@ -58,7 +58,18 @@ window.onload = function() { window.setTimeout(function() { // Get parameter information, so we can retrieve connecton data - var data = window.location.search.substr(1); + var params = window.location.search.substr(1); + var data = ""; + var exitUrl = ""; + var ioa = params.indexOf('&'); + // URL is in the format ?XXXXXXXX&URL, where XXX is the id of the credential stored, and URL is the output URL + if( ioa != -1 ) { + data = params.substr(0,ioa); + exiturl = params.substr(ioa+1); + } + else { + data = params; + } // Get display div from document var display = document.getElementById("display"); @@ -76,6 +87,12 @@ // Error handler guac.onerror = function(error) { alert(error); + window.location.assign(exiturl); + }; + + guac.onstatechange = function(state) { + if( state == 0 || state == 4 || state == 5 ) + window.location.assign(exiturl); }; var optimal_width = window.innerWidth;