diff --git a/guacamole/web-client/doc/example/guacamole.properties b/guacamole/web-client/doc/example/guacamole.properties
new file mode 100644
index 000000000..fb8b93900
--- /dev/null
+++ b/guacamole/web-client/doc/example/guacamole.properties
@@ -0,0 +1,26 @@
+
+# Guacamole - Clientless Remote Desktop
+# Copyright (C) 2010 Michael Jumper
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+
+# Hostname and port of guacamole proxy
+guacd-hostname: localhost
+guacd-port: 4822
+
+# Session provider class (provides and configured guacamole session based on authentication information)
+session-provider: net.sourceforge.guacamole.basic.BasicGuacamoleSessionProvider
+basic-user-mapping: /path/to/user-mapping.xml
+
diff --git a/guacamole/web-client/doc/example/guacamole.xml b/guacamole/web-client/doc/example/guacamole.xml
deleted file mode 100644
index aeb6208b6..000000000
--- a/guacamole/web-client/doc/example/guacamole.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/guacamole/web-client/src/net/sourceforge/guacamole/basic/BasicLogin.java b/guacamole/web-client/src/net/sourceforge/guacamole/basic/BasicLogin.java
deleted file mode 100644
index 2733abde9..000000000
--- a/guacamole/web-client/src/net/sourceforge/guacamole/basic/BasicLogin.java
+++ /dev/null
@@ -1,149 +0,0 @@
-
-package net.sourceforge.guacamole.basic;
-
-import java.io.File;
-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 long mappingTime;
- 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;
- }
-
- }
-
- private File getUserMappingFile() {
-
- // Get user mapping filename
- ServletContext context = getServletContext();
- String filename = context.getInitParameter("basic-user-mapping");
- if (filename == null)
- return null;
-
- return new File(filename);
-
- }
-
- @Override
- public synchronized void init() throws ServletException {
-
- // Get user mapping file
- File mapFile = getUserMappingFile();
- if (mapFile == 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(mapFile.getAbsolutePath());
-
- mappingTime = mapFile.lastModified();
- 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 {
-
- // Check mapping file mod time
- File userMappingFile = getUserMappingFile();
- if (userMappingFile.exists() && mappingTime < userMappingFile.lastModified()) {
-
- // If modified recently, gain exclusive access and recheck
- synchronized (this) {
- if (userMappingFile.exists() && mappingTime < userMappingFile.lastModified())
- init(); // If still not up to date, re-init
- }
-
- }
-
- // 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.validate(username, 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
deleted file mode 100644
index ea282c448..000000000
--- a/guacamole/web-client/src/net/sourceforge/guacamole/basic/BasicUserMappingContentHandler.java
+++ /dev/null
@@ -1,217 +0,0 @@
-
-package net.sourceforge.guacamole.basic;
-
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-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 static class AuthInfo {
-
- public static enum Encoding {
- PLAIN_TEXT,
- MD5
- }
-
- private String auth_username;
- private String auth_password;
- private Encoding auth_encoding;
-
- private String protocol;
- private String hostname;
- private int port;
- private String password;
-
- public AuthInfo(String auth_username, String auth_password, Encoding auth_encoding) {
- this.auth_username = auth_username;
- this.auth_password = auth_password;
- this.auth_encoding = auth_encoding;
- }
-
- private static final char HEX_CHARS[] = {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
- };
-
- public static String getHexString(byte[] bytes) {
-
- if (bytes == null)
- return null;
-
- StringBuilder hex = new StringBuilder(2 * bytes.length);
- for (byte b : bytes) {
- hex.append(HEX_CHARS[(b & 0xF0) >> 4])
- .append(HEX_CHARS[(b & 0x0F) ]);
- }
-
- return hex.toString();
-
- }
-
-
- public boolean validate(String username, String password) {
-
- // If username matches
- if (username != null && password != null && username.equals(auth_username)) {
-
- switch (auth_encoding) {
-
- case PLAIN_TEXT:
-
- // Compare plaintext
- return password.equals(auth_password);
-
- case MD5:
-
- // Compare hashed password
- try {
- MessageDigest digest = MessageDigest.getInstance("MD5");
- String hashedPassword = getHexString(digest.digest(password.getBytes()));
- return hashedPassword.equals(auth_password.toUpperCase());
- }
- catch (NoSuchAlgorithmException e) {
- throw new UnsupportedOperationException("Unexpected lack of MD5 support.", e);
- }
-
- }
-
- }
-
- return false;
-
- }
-
- 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.auth_username,
- current
- );
-
- }
-
- infoState = null;
-
- }
-
- @Override
- public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
-
- if (localName.equals("authorize")) {
-
- AuthInfo.Encoding encoding;
- String encodingString = attributes.getValue("encoding");
- if (encodingString == null)
- encoding = AuthInfo.Encoding.PLAIN_TEXT;
- else if (encodingString.equals("plain"))
- encoding = AuthInfo.Encoding.PLAIN_TEXT;
- else if (encodingString.equals("md5"))
- encoding = AuthInfo.Encoding.MD5;
- else
- throw new SAXException("Invalid encoding type");
-
-
- current = new AuthInfo(
- attributes.getValue("username"),
- attributes.getValue("password"),
- encoding
- );
-
- 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/src/net/sourceforge/guacamole/net/Configuration.java b/guacamole/web-client/src/net/sourceforge/guacamole/net/Configuration.java
index b8bc8d057..6e78eb296 100644
--- a/guacamole/web-client/src/net/sourceforge/guacamole/net/Configuration.java
+++ b/guacamole/web-client/src/net/sourceforge/guacamole/net/Configuration.java
@@ -24,8 +24,6 @@ import net.sourceforge.guacamole.GuacamoleException;
public abstract class Configuration {
- private ServletContext context;
-
protected String humanReadableList(Object... values) {
String list = "";
@@ -44,9 +42,14 @@ public abstract class Configuration {
}
+ protected String readParameter(String name) throws GuacamoleException {
+ String value = GuacamoleProperties.getProperty(name);
+ return value;
+ }
+
protected String readParameter(String name, String defaultValue, String... allowedValues) throws GuacamoleException {
- String value = context.getInitParameter(name);
+ String value = GuacamoleProperties.getProperty(name);
// Use default if not specified
if (value == null) {
@@ -70,7 +73,7 @@ public abstract class Configuration {
protected boolean readBooleanParameter(String name, Boolean defaultValue) throws GuacamoleException {
- String value = context.getInitParameter(name);
+ String value = GuacamoleProperties.getProperty(name);
// Use default if not specified
if (value == null) {
@@ -93,7 +96,7 @@ public abstract class Configuration {
protected int readIntParameter(String name, Integer defaultValue, Integer... allowedValues) throws GuacamoleException {
- String parmString = context.getInitParameter(name);
+ String parmString = GuacamoleProperties.getProperty(name);
// Use default if not specified
if (parmString== null) {
@@ -123,8 +126,4 @@ public abstract class Configuration {
}
- public Configuration(ServletContext context) {
- this.context = context;
- }
-
}
diff --git a/guacamole/web-client/src/net/sourceforge/guacamole/net/GuacamoleConfiguration.java b/guacamole/web-client/src/net/sourceforge/guacamole/net/GuacamoleConfiguration.java
index ac56cb825..a6bfeeb52 100644
--- a/guacamole/web-client/src/net/sourceforge/guacamole/net/GuacamoleConfiguration.java
+++ b/guacamole/web-client/src/net/sourceforge/guacamole/net/GuacamoleConfiguration.java
@@ -19,8 +19,8 @@ package net.sourceforge.guacamole.net;
* along with this program. If not, see .
*/
+import net.sourceforge.guacamole.net.authentication.GuacamoleSessionProvider;
import java.lang.reflect.InvocationTargetException;
-import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import net.sourceforge.guacamole.GuacamoleException;
@@ -30,16 +30,14 @@ public class GuacamoleConfiguration extends Configuration {
private int guacd_port;
private GuacamoleSessionProvider sessionProvider;
- public GuacamoleConfiguration(ServletContext context) throws GuacamoleException {
+ public GuacamoleConfiguration() throws GuacamoleException {
- super(context);
-
- guacd_hostname = context.getInitParameter("guacd-hostname");
+ guacd_hostname = readParameter("guacd-hostname");
guacd_port = readIntParameter("guacd-port", null);
// Get session provider instance
try {
- String sessionProviderClassName = context.getInitParameter("session-provider");
+ String sessionProviderClassName = readParameter("session-provider");
Object obj = Class.forName(sessionProviderClassName).getConstructor().newInstance();
if (!(obj instanceof GuacamoleSessionProvider))
throw new GuacamoleException("Specified session provider class is not a GuacamoleSessionProvider");
diff --git a/guacamole/web-client/src/net/sourceforge/guacamole/net/GuacamoleProperties.java b/guacamole/web-client/src/net/sourceforge/guacamole/net/GuacamoleProperties.java
new file mode 100644
index 000000000..25eef84ca
--- /dev/null
+++ b/guacamole/web-client/src/net/sourceforge/guacamole/net/GuacamoleProperties.java
@@ -0,0 +1,31 @@
+
+package net.sourceforge.guacamole.net;
+
+import java.io.IOException;
+import java.util.Properties;
+import javax.servlet.ServletException;
+import net.sourceforge.guacamole.GuacamoleException;
+import net.sourceforge.guacamole.net.authentication.basic.BasicLogin;
+
+public class GuacamoleProperties {
+
+ private static final Properties properties = new Properties();
+ private static GuacamoleException exception;
+
+ static {
+
+ try {
+ properties.load(BasicLogin.class.getResourceAsStream("/guacamole.properties"));
+ }
+ catch (IOException e) {
+ exception = new GuacamoleException("Error reading guacamole.properties", e);
+ }
+
+ }
+
+ public static String getProperty(String name) throws GuacamoleException {
+ if (exception != null) throw exception;
+ return properties.getProperty(name);
+ }
+
+}
diff --git a/guacamole/web-client/src/net/sourceforge/guacamole/net/GuacamoleServlet.java b/guacamole/web-client/src/net/sourceforge/guacamole/net/GuacamoleServlet.java
index 0ccbff9e3..a1e713132 100644
--- a/guacamole/web-client/src/net/sourceforge/guacamole/net/GuacamoleServlet.java
+++ b/guacamole/web-client/src/net/sourceforge/guacamole/net/GuacamoleServlet.java
@@ -33,9 +33,9 @@ public abstract class GuacamoleServlet extends HttpServlet {
private GuacamoleConfiguration config;
@Override
- public void init(ServletConfig config) throws ServletException {
+ public void init() throws ServletException {
try {
- this.config = new GuacamoleConfiguration(config.getServletContext());
+ this.config = new GuacamoleConfiguration();
}
catch (GuacamoleException e) {
throw new ServletException(e);
diff --git a/guacamole/web-client/src/net/sourceforge/guacamole/net/GuacamoleSession.java b/guacamole/web-client/src/net/sourceforge/guacamole/net/GuacamoleSession.java
index 650f2fce5..2eb01326b 100644
--- a/guacamole/web-client/src/net/sourceforge/guacamole/net/GuacamoleSession.java
+++ b/guacamole/web-client/src/net/sourceforge/guacamole/net/GuacamoleSession.java
@@ -104,8 +104,7 @@ public class GuacamoleSession {
synchronized (session) {
// Read configuration parameters
- ServletContext context = session.getServletContext();
- config = new GuacamoleConfiguration(context);
+ config = new GuacamoleConfiguration();
client = (SessionClient) session.getAttribute("CLIENT");
instructionStreamLock = (ReentrantLock) session.getAttribute("INSTRUCTION_STREAM_LOCK");
diff --git a/guacamole/web-client/src/net/sourceforge/guacamole/net/GuacamoleSessionProvider.java b/guacamole/web-client/src/net/sourceforge/guacamole/net/authentication/GuacamoleSessionProvider.java
similarity index 90%
rename from guacamole/web-client/src/net/sourceforge/guacamole/net/GuacamoleSessionProvider.java
rename to guacamole/web-client/src/net/sourceforge/guacamole/net/authentication/GuacamoleSessionProvider.java
index 3bcd25876..bbe82a2de 100644
--- a/guacamole/web-client/src/net/sourceforge/guacamole/net/GuacamoleSessionProvider.java
+++ b/guacamole/web-client/src/net/sourceforge/guacamole/net/authentication/GuacamoleSessionProvider.java
@@ -1,8 +1,9 @@
-package net.sourceforge.guacamole.net;
+package net.sourceforge.guacamole.net.authentication;
import javax.servlet.http.HttpSession;
import net.sourceforge.guacamole.GuacamoleException;
+import net.sourceforge.guacamole.net.GuacamoleSession;
/*
* Guacamole - Clientless Remote Desktop
diff --git a/guacamole/web-client/src/net/sourceforge/guacamole/net/NullGuacamoleSessionProvider.java b/guacamole/web-client/src/net/sourceforge/guacamole/net/authentication/NullGuacamoleSessionProvider.java
similarity index 91%
rename from guacamole/web-client/src/net/sourceforge/guacamole/net/NullGuacamoleSessionProvider.java
rename to guacamole/web-client/src/net/sourceforge/guacamole/net/authentication/NullGuacamoleSessionProvider.java
index bb0e75532..a46d0fe57 100644
--- a/guacamole/web-client/src/net/sourceforge/guacamole/net/NullGuacamoleSessionProvider.java
+++ b/guacamole/web-client/src/net/sourceforge/guacamole/net/authentication/NullGuacamoleSessionProvider.java
@@ -1,8 +1,9 @@
-package net.sourceforge.guacamole.net;
+package net.sourceforge.guacamole.net.authentication;
import javax.servlet.http.HttpSession;
import net.sourceforge.guacamole.GuacamoleException;
+import net.sourceforge.guacamole.net.GuacamoleSession;
/*
* Guacamole - Clientless Remote Desktop
diff --git a/guacamole/web-client/src/net/sourceforge/guacamole/net/authentication/basic/BasicFileAuthenticationProvider.java b/guacamole/web-client/src/net/sourceforge/guacamole/net/authentication/basic/BasicFileAuthenticationProvider.java
new file mode 100644
index 000000000..34a631279
--- /dev/null
+++ b/guacamole/web-client/src/net/sourceforge/guacamole/net/authentication/basic/BasicFileAuthenticationProvider.java
@@ -0,0 +1,300 @@
+
+package net.sourceforge.guacamole.net.authentication.basic;
+
+import java.io.File;
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import net.sourceforge.guacamole.GuacamoleException;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+public class BasicFileAuthenticationProvider implements BasicLogin.AuthenticationProvider {
+
+ private long mappingTime;
+ private Map mapping;
+
+ private File getUserMappingFile() {
+
+ // Get user mapping filename
+ //String filename = context.getInitParameter("basic-user-mapping");
+ String filename = ""; // FIXME
+ if (filename == null)
+ return null;
+
+ return new File(filename);
+
+ }
+
+ public synchronized void init() throws GuacamoleException {
+
+ // Get user mapping file
+ File mapFile = getUserMappingFile();
+ if (mapFile == null)
+ throw new GuacamoleException("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(mapFile.getAbsolutePath());
+
+ mappingTime = mapFile.lastModified();
+ mapping = contentHandler.getUserMapping();
+
+ }
+ catch (IOException e) {
+ throw new GuacamoleException("Error reading basic user mapping file.", e);
+ }
+ catch (SAXException e) {
+ throw new GuacamoleException("Error parsing basic user mapping XML.", e);
+ }
+
+ }
+
+ @Override
+ public BasicLogin.AuthorizedConfiguration getAuthorizedConfiguration(String username, String password) throws GuacamoleException {
+
+ // Check mapping file mod time
+ File userMappingFile = getUserMappingFile();
+ if (userMappingFile.exists() && mappingTime < userMappingFile.lastModified()) {
+
+ // If modified recently, gain exclusive access and recheck
+ synchronized (this) {
+ if (userMappingFile.exists() && mappingTime < userMappingFile.lastModified())
+ init(); // If still not up to date, re-init
+ }
+
+ }
+
+ AuthInfo info = mapping.get(username);
+ if (info != null && info.validate(username, password))
+ return new BasicLogin.AuthorizedConfiguration(
+ info.getProtocol(),
+ info.getHostname(),
+ info.getPort(),
+ info.getPassword()
+ );
+
+ return null;
+
+ }
+
+ public static class AuthInfo {
+
+ public static enum Encoding {
+ PLAIN_TEXT,
+ MD5
+ }
+
+ private String auth_username;
+ private String auth_password;
+ private Encoding auth_encoding;
+
+ private String protocol;
+ private String hostname;
+ private int port;
+ private String password;
+
+ public AuthInfo(String auth_username, String auth_password, Encoding auth_encoding) {
+ this.auth_username = auth_username;
+ this.auth_password = auth_password;
+ this.auth_encoding = auth_encoding;
+ }
+
+ private static final char HEX_CHARS[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+ };
+
+ public static String getHexString(byte[] bytes) {
+
+ if (bytes == null)
+ return null;
+
+ StringBuilder hex = new StringBuilder(2 * bytes.length);
+ for (byte b : bytes) {
+ hex.append(HEX_CHARS[(b & 0xF0) >> 4])
+ .append(HEX_CHARS[(b & 0x0F) ]);
+ }
+
+ return hex.toString();
+
+ }
+
+
+ public boolean validate(String username, String password) {
+
+ // If username matches
+ if (username != null && password != null && username.equals(auth_username)) {
+
+ switch (auth_encoding) {
+
+ case PLAIN_TEXT:
+
+ // Compare plaintext
+ return password.equals(auth_password);
+
+ case MD5:
+
+ // Compare hashed password
+ try {
+ MessageDigest digest = MessageDigest.getInstance("MD5");
+ String hashedPassword = getHexString(digest.digest(password.getBytes()));
+ return hashedPassword.equals(auth_password.toUpperCase());
+ }
+ catch (NoSuchAlgorithmException e) {
+ throw new UnsupportedOperationException("Unexpected lack of MD5 support.", e);
+ }
+
+ }
+
+ }
+
+ return false;
+
+ }
+
+ public String getHostname() {
+ return hostname;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public String getProtocol() {
+ return protocol;
+ }
+
+ }
+
+
+ private static class BasicUserMappingContentHandler extends DefaultHandler {
+
+ private Map authMapping = new HashMap();
+
+ public Map getUserMapping() {
+ return Collections.unmodifiableMap(authMapping);
+ }
+
+ 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.auth_username,
+ current
+ );
+
+ }
+
+ infoState = null;
+
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+
+ if (localName.equals("authorize")) {
+
+ AuthInfo.Encoding encoding;
+ String encodingString = attributes.getValue("encoding");
+ if (encodingString == null)
+ encoding = AuthInfo.Encoding.PLAIN_TEXT;
+ else if (encodingString.equals("plain"))
+ encoding = AuthInfo.Encoding.PLAIN_TEXT;
+ else if (encodingString.equals("md5"))
+ encoding = AuthInfo.Encoding.MD5;
+ else
+ throw new SAXException("Invalid encoding type");
+
+
+ current = new AuthInfo(
+ attributes.getValue("username"),
+ attributes.getValue("password"),
+ encoding
+ );
+
+ 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/src/net/sourceforge/guacamole/basic/BasicGuacamoleSessionProvider.java b/guacamole/web-client/src/net/sourceforge/guacamole/net/authentication/basic/BasicGuacamoleSessionProvider.java
similarity index 92%
rename from guacamole/web-client/src/net/sourceforge/guacamole/basic/BasicGuacamoleSessionProvider.java
rename to guacamole/web-client/src/net/sourceforge/guacamole/net/authentication/basic/BasicGuacamoleSessionProvider.java
index 75997bdb4..959bf0e6e 100644
--- a/guacamole/web-client/src/net/sourceforge/guacamole/basic/BasicGuacamoleSessionProvider.java
+++ b/guacamole/web-client/src/net/sourceforge/guacamole/net/authentication/basic/BasicGuacamoleSessionProvider.java
@@ -1,10 +1,10 @@
-package net.sourceforge.guacamole.basic;
+package net.sourceforge.guacamole.net.authentication.basic;
import javax.servlet.http.HttpSession;
import net.sourceforge.guacamole.GuacamoleException;
import net.sourceforge.guacamole.net.GuacamoleSession;
-import net.sourceforge.guacamole.net.GuacamoleSessionProvider;
+import net.sourceforge.guacamole.net.authentication.GuacamoleSessionProvider;
/*
* Guacamole - Clientless Remote Desktop
diff --git a/guacamole/web-client/src/net/sourceforge/guacamole/net/authentication/basic/BasicLogin.java b/guacamole/web-client/src/net/sourceforge/guacamole/net/authentication/basic/BasicLogin.java
new file mode 100644
index 000000000..76287bd01
--- /dev/null
+++ b/guacamole/web-client/src/net/sourceforge/guacamole/net/authentication/basic/BasicLogin.java
@@ -0,0 +1,89 @@
+
+package net.sourceforge.guacamole.net.authentication.basic;
+
+import java.io.IOException;
+import java.util.Properties;
+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.GuacamoleException;
+
+public class BasicLogin extends HttpServlet {
+
+ private AuthenticationProvider authProvider;
+
+ public static interface AuthenticationProvider {
+ public AuthorizedConfiguration getAuthorizedConfiguration(String username, String password) throws GuacamoleException;
+ }
+
+ // Added to session when session validated
+ public static 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
+ 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");
+
+ // Validate username and password
+ try {
+
+ AuthorizedConfiguration info = authProvider.getAuthorizedConfiguration(username, password);
+ if (info != null) {
+
+ // Store authorized configuration
+ HttpSession session = req.getSession(true);
+ session.setAttribute(
+ "BASIC-LOGIN-AUTH",
+ info
+ );
+
+ // Success
+ return;
+
+ }
+
+ // Report "forbidden" on any failure
+ resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Login invalid");
+ }
+ catch (GuacamoleException e) {
+ throw new ServletException("Error validating credentials", e);
+ }
+
+ }
+
+
+}
diff --git a/guacamole/web-client/web/META-INF/context.xml b/guacamole/web-client/web/META-INF/context.xml
new file mode 100644
index 000000000..5bee3dc30
--- /dev/null
+++ b/guacamole/web-client/web/META-INF/context.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/guacamole/web-client/web/WEB-INF/web.xml b/guacamole/web-client/web/WEB-INF/web.xml
index 216304c13..c7cbc9fb6 100644
--- a/guacamole/web-client/web/WEB-INF/web.xml
+++ b/guacamole/web-client/web/WEB-INF/web.xml
@@ -17,18 +17,15 @@
along with this program. If not, see .
-->
-
index.html
-
30
-
Connect servlet.
@@ -57,15 +54,13 @@
Inbound
/inbound
-
BasicLogin
- net.sourceforge.guacamole.basic.BasicLogin
+ net.sourceforge.guacamole.net.authentication.basic.BasicLogin
BasicLogin
/login
-