diff --git a/guacamole/web-client/doc/example/guacamole-users.xml b/guacamole/web-client/doc/example/guacamole-users.xml
deleted file mode 100644
index 50bb77a12..000000000
--- a/guacamole/web-client/doc/example/guacamole-users.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/guacamole/web-client/doc/example/guacamole.xml b/guacamole/web-client/doc/example/guacamole.xml
index 7499ca2ff..aeb6208b6 100644
--- a/guacamole/web-client/doc/example/guacamole.xml
+++ b/guacamole/web-client/doc/example/guacamole.xml
@@ -18,12 +18,16 @@
along with this program. If not, see .
-->
+
-
-
+
+
+
+
+
+
-
diff --git a/guacamole/web-client/doc/example/user-mapping.xml b/guacamole/web-client/doc/example/user-mapping.xml
new file mode 100644
index 000000000..f006887f9
--- /dev/null
+++ b/guacamole/web-client/doc/example/user-mapping.xml
@@ -0,0 +1,11 @@
+
+
+
+
+ vnc
+ localhost
+ 5900
+ VNCPASS
+
+
+
diff --git a/guacamole/web-client/src/net/sourceforge/guacamole/net/BasicGuacamoleSessionProvider.java b/guacamole/web-client/src/net/sourceforge/guacamole/basic/BasicGuacamoleSessionProvider.java
similarity index 59%
rename from guacamole/web-client/src/net/sourceforge/guacamole/net/BasicGuacamoleSessionProvider.java
rename to guacamole/web-client/src/net/sourceforge/guacamole/basic/BasicGuacamoleSessionProvider.java
index 85dcb3fbd..75997bdb4 100644
--- a/guacamole/web-client/src/net/sourceforge/guacamole/net/BasicGuacamoleSessionProvider.java
+++ b/guacamole/web-client/src/net/sourceforge/guacamole/basic/BasicGuacamoleSessionProvider.java
@@ -1,8 +1,10 @@
-package net.sourceforge.guacamole.net;
+package net.sourceforge.guacamole.basic;
import javax.servlet.http.HttpSession;
import net.sourceforge.guacamole.GuacamoleException;
+import net.sourceforge.guacamole.net.GuacamoleSession;
+import net.sourceforge.guacamole.net.GuacamoleSessionProvider;
/*
* Guacamole - Clientless Remote Desktop
@@ -26,11 +28,21 @@ public class BasicGuacamoleSessionProvider implements GuacamoleSessionProvider {
public GuacamoleSession createSession(HttpSession session) throws GuacamoleException {
+ // Retrieve authorized config data from session
+ BasicLogin.AuthorizedConfiguration config = (BasicLogin.AuthorizedConfiguration)
+ session.getAttribute("BASIC-LOGIN-AUTH");
+
+ // If no data, not authorized
+ if (config == null)
+ throw new GuacamoleException("Unauthorized");
+
+ // Configure session from authorized config info
GuacamoleSession guacSession = new GuacamoleSession(session);
+ guacSession.setConnection(config.getProtocol(), config.getHostname(), config.getPort());
+ if (config.getPassword() != null)
+ guacSession.setPassword(config.getPassword());
- guacSession.setConnection("vnc", "localhost", 5901);
- guacSession.setPassword("potato");
-
+ // Return authorized session
return guacSession;
}
diff --git a/guacamole/web-client/src/net/sourceforge/guacamole/basic/BasicLogin.java b/guacamole/web-client/src/net/sourceforge/guacamole/basic/BasicLogin.java
new file mode 100644
index 000000000..f73b8974b
--- /dev/null
+++ b/guacamole/web-client/src/net/sourceforge/guacamole/basic/BasicLogin.java
@@ -0,0 +1,125 @@
+
+package net.sourceforge.guacamole.basic;
+
+import java.io.IOException;
+import java.util.Map;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import net.sourceforge.guacamole.basic.BasicUserMappingContentHandler.AuthInfo;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+public class BasicLogin extends HttpServlet {
+
+ private Map mapping;
+
+ // Added to session when session validated
+ public class AuthorizedConfiguration {
+
+ private String protocol;
+ private String hostname;
+ private int port;
+ private String password;
+
+ public AuthorizedConfiguration(String protocol, String hostname, int port, String password) {
+ this.protocol = protocol;
+ this.hostname = hostname;
+ this.port = port;
+ this.password = password;
+ }
+
+ public String getHostname() {
+ return hostname;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public String getProtocol() {
+ return protocol;
+ }
+
+ }
+
+ @Override
+ public void init() throws ServletException {
+
+ // Get user mapping filename
+ ServletContext context = getServletContext();
+ String filename = context.getInitParameter("basic-user-mapping");
+ if (filename == null)
+ throw new ServletException("Missing \"basic-user-mapping\" parameter required for basic login.");
+
+ // Parse document
+ try {
+
+ BasicUserMappingContentHandler contentHandler = new BasicUserMappingContentHandler();
+
+ XMLReader parser = XMLReaderFactory.createXMLReader();
+ parser.setContentHandler(contentHandler);
+ parser.parse(filename);
+
+ mapping = contentHandler.getUserMapping();
+
+ }
+ catch (IOException e) {
+ throw new ServletException("Error reading basic user mapping file.", e);
+ }
+ catch (SAXException e) {
+ throw new ServletException("Error parsing basic user mapping XML.", e);
+ }
+
+
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+
+ // Retrieve username and password from parms
+ String username = req.getParameter("username");
+ String password = req.getParameter("password");
+
+ // Retrieve corresponding authorization info
+ AuthInfo info = mapping.get(username);
+ if (info != null) {
+
+ // Validate username and password
+ if (info.getAuthorizedUsername().equals(username)
+ && info.getAuthorizedPassword().equals(password)) {
+
+ // Store authorized configuration
+ HttpSession session = req.getSession(true);
+ session.setAttribute(
+ "BASIC-LOGIN-AUTH",
+ new AuthorizedConfiguration(
+ info.getProtocol(),
+ info.getHostname(),
+ info.getPort(),
+ info.getPassword()
+ )
+ );
+
+ // Success
+ return;
+
+ }
+
+ }
+
+ // Report "forbidden" on any failure
+ resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Login invalid");
+
+ }
+
+
+}
diff --git a/guacamole/web-client/src/net/sourceforge/guacamole/basic/BasicUserMappingContentHandler.java b/guacamole/web-client/src/net/sourceforge/guacamole/basic/BasicUserMappingContentHandler.java
new file mode 100644
index 000000000..6f71ebf30
--- /dev/null
+++ b/guacamole/web-client/src/net/sourceforge/guacamole/basic/BasicUserMappingContentHandler.java
@@ -0,0 +1,150 @@
+
+package net.sourceforge.guacamole.basic;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+public class BasicUserMappingContentHandler extends DefaultHandler {
+
+ private Map authMapping = new HashMap();
+
+ public Map getUserMapping() {
+ return Collections.unmodifiableMap(authMapping);
+ }
+
+ public class AuthInfo {
+
+ private String auth_username;
+ private String auth_password;
+
+ private String protocol;
+ private String hostname;
+ private int port;
+ private String password;
+
+ public AuthInfo(String auth_username, String auth_password) {
+ this.auth_username = auth_username;
+ this.auth_password = auth_password;
+ }
+
+ public String getAuthorizedUsername() {
+ return auth_username;
+ }
+
+ public String getAuthorizedPassword() {
+ return auth_password;
+ }
+
+ public String getHostname() {
+ return hostname;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public String getProtocol() {
+ return protocol;
+ }
+
+ }
+
+ private AuthInfo current;
+
+ private enum AUTH_INFO_STATE {
+ PROTOCOL,
+ HOSTNAME,
+ PORT,
+ PASSWORD
+ };
+
+ private AUTH_INFO_STATE infoState;
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+
+ if (localName.equals("authorize")) {
+
+ // Finalize mapping for this user
+ authMapping.put(
+ current.getAuthorizedUsername(),
+ current
+ );
+
+ }
+
+ infoState = null;
+
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+
+ if (localName.equals("authorize")) {
+
+ current = new AuthInfo(
+ attributes.getValue("username"),
+ attributes.getValue("password")
+ );
+
+ infoState = null;
+
+ }
+
+ else if (localName.equals("protocol"))
+ infoState = AUTH_INFO_STATE.PROTOCOL;
+
+ else if (localName.equals("hostname"))
+ infoState = AUTH_INFO_STATE.HOSTNAME;
+
+ else if (localName.equals("port"))
+ infoState = AUTH_INFO_STATE.PORT;
+
+ else if (localName.equals("password"))
+ infoState = AUTH_INFO_STATE.PASSWORD;
+
+ else
+ infoState = null;
+
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length) throws SAXException {
+
+ String str = new String(ch, start, length);
+
+ if (infoState == null)
+ return;
+
+ switch (infoState) {
+
+ case PROTOCOL:
+ current.protocol = str;
+ break;
+
+ case HOSTNAME:
+ current.hostname = str;
+ break;
+
+ case PORT:
+ current.port = Integer.parseInt(str);
+ break;
+
+ case PASSWORD:
+ current.password = str;
+ break;
+
+ }
+
+ }
+
+
+}
diff --git a/guacamole/web-client/web/META-INF/context.xml b/guacamole/web-client/web/META-INF/context.xml
deleted file mode 100644
index ea825baf9..000000000
--- a/guacamole/web-client/web/META-INF/context.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/guacamole/web-client/web/WEB-INF/web.xml b/guacamole/web-client/web/WEB-INF/web.xml
index 0be425c7f..216304c13 100644
--- a/guacamole/web-client/web/WEB-INF/web.xml
+++ b/guacamole/web-client/web/WEB-INF/web.xml
@@ -17,9 +17,8 @@
along with this program. If not, see .
-->
-
+
-
index.html
@@ -29,9 +28,8 @@
30
-
-
+
Connect servlet.
Connect
@@ -41,7 +39,6 @@
Connect
/connect
-
Outbound servlet.
Outbound
@@ -51,7 +48,6 @@
Outbound
/outbound
-
Input servlet.
Inbound
@@ -61,5 +57,15 @@
Inbound
/inbound
-
+
+
+
+ BasicLogin
+ net.sourceforge.guacamole.basic.BasicLogin
+
+
+ BasicLogin
+ /login
+
+
diff --git a/guacamole/web-client/web/guacamole.css b/guacamole/web-client/web/guacamole.css
index bd0e7c80f..4a0cbf533 100644
--- a/guacamole/web-client/web/guacamole.css
+++ b/guacamole/web-client/web/guacamole.css
@@ -34,6 +34,13 @@ div#login-ui {
display: table;
}
+p#login-error {
+ text-align: center;
+ background: #FDD;
+ color: red;
+ margin: 0.2em;
+}
+
div#login-logo {
position: relative;
bottom: 0;
@@ -71,19 +78,18 @@ div#login-dialog h1 {
margin-top: 0;
margin-bottom: 0em;
text-align: center;
- border-bottom: 1px solid silver;
- padding-bottom: 0.5em;
}
div#login-dialog #buttons {
- border-top: 1px solid silver;
padding-top: 0.5em;
text-align: center;
}
div#login-dialog #login-fields {
- margin-top: 0.5em;
- margin-bottom: 0.5em;
+ border-top: 1px solid silver;
+ border-bottom: 1px solid silver;
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
}
div.errorDialogOuter {
diff --git a/guacamole/web-client/web/index.html b/guacamole/web-client/web/index.html
index f6a53aabb..77d939b51 100644
--- a/guacamole/web-client/web/index.html
+++ b/guacamole/web-client/web/index.html
@@ -40,6 +40,9 @@