Initial auth provider, using properties instead of XML

This commit is contained in:
Michael Jumper
2010-12-05 14:33:43 -08:00
parent a1f0de62b9
commit f99f9cff15
16 changed files with 470 additions and 428 deletions

View File

@@ -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 <http://www.gnu.org/licenses/>.
# 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

View File

@@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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 <http://www.gnu.org/licenses/>.
-->
<?xml version="1.0" encoding="UTF-8"?>
<Context antiJARLocking="true" path="/guacamole" docBase="/var/lib/guacamole/guacamole.war">
<!-- Change the lines below to match your Guacamole proxy -->
<Parameter name="guacd-hostname" value="localhost"/>
<Parameter name="guacd-port" value="4822"/>
<!-- Session provider class (provides and configured guacamole session based on authentication information) -->
<Parameter name="session-provider" value="net.sourceforge.guacamole.basic.BasicGuacamoleSessionProvider"/>
<Parameter name="basic-user-mapping" value="/path/to/user-mapping.xml"/>
</Context>

View File

@@ -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<String, AuthInfo> 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");
}
}

View File

@@ -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<String, AuthInfo> authMapping = new HashMap<String, AuthInfo>();
public Map<String, AuthInfo> 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;
}
}
}

View File

@@ -24,8 +24,6 @@ import net.sourceforge.guacamole.GuacamoleException;
public abstract class Configuration { public abstract class Configuration {
private ServletContext context;
protected String humanReadableList(Object... values) { protected String humanReadableList(Object... values) {
String list = ""; 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 { 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 // Use default if not specified
if (value == null) { if (value == null) {
@@ -70,7 +73,7 @@ public abstract class Configuration {
protected boolean readBooleanParameter(String name, Boolean defaultValue) throws GuacamoleException { protected boolean readBooleanParameter(String name, Boolean defaultValue) throws GuacamoleException {
String value = context.getInitParameter(name); String value = GuacamoleProperties.getProperty(name);
// Use default if not specified // Use default if not specified
if (value == null) { if (value == null) {
@@ -93,7 +96,7 @@ public abstract class Configuration {
protected int readIntParameter(String name, Integer defaultValue, Integer... allowedValues) throws GuacamoleException { 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 // Use default if not specified
if (parmString== null) { if (parmString== null) {
@@ -123,8 +126,4 @@ public abstract class Configuration {
} }
public Configuration(ServletContext context) {
this.context = context;
}
} }

View File

@@ -19,8 +19,8 @@ package net.sourceforge.guacamole.net;
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import net.sourceforge.guacamole.net.authentication.GuacamoleSessionProvider;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
import net.sourceforge.guacamole.GuacamoleException; import net.sourceforge.guacamole.GuacamoleException;
@@ -30,16 +30,14 @@ public class GuacamoleConfiguration extends Configuration {
private int guacd_port; private int guacd_port;
private GuacamoleSessionProvider sessionProvider; private GuacamoleSessionProvider sessionProvider;
public GuacamoleConfiguration(ServletContext context) throws GuacamoleException { public GuacamoleConfiguration() throws GuacamoleException {
super(context); guacd_hostname = readParameter("guacd-hostname");
guacd_hostname = context.getInitParameter("guacd-hostname");
guacd_port = readIntParameter("guacd-port", null); guacd_port = readIntParameter("guacd-port", null);
// Get session provider instance // Get session provider instance
try { try {
String sessionProviderClassName = context.getInitParameter("session-provider"); String sessionProviderClassName = readParameter("session-provider");
Object obj = Class.forName(sessionProviderClassName).getConstructor().newInstance(); Object obj = Class.forName(sessionProviderClassName).getConstructor().newInstance();
if (!(obj instanceof GuacamoleSessionProvider)) if (!(obj instanceof GuacamoleSessionProvider))
throw new GuacamoleException("Specified session provider class is not a GuacamoleSessionProvider"); throw new GuacamoleException("Specified session provider class is not a GuacamoleSessionProvider");

View File

@@ -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);
}
}

View File

@@ -33,9 +33,9 @@ public abstract class GuacamoleServlet extends HttpServlet {
private GuacamoleConfiguration config; private GuacamoleConfiguration config;
@Override @Override
public void init(ServletConfig config) throws ServletException { public void init() throws ServletException {
try { try {
this.config = new GuacamoleConfiguration(config.getServletContext()); this.config = new GuacamoleConfiguration();
} }
catch (GuacamoleException e) { catch (GuacamoleException e) {
throw new ServletException(e); throw new ServletException(e);

View File

@@ -104,8 +104,7 @@ public class GuacamoleSession {
synchronized (session) { synchronized (session) {
// Read configuration parameters // Read configuration parameters
ServletContext context = session.getServletContext(); config = new GuacamoleConfiguration();
config = new GuacamoleConfiguration(context);
client = (SessionClient) session.getAttribute("CLIENT"); client = (SessionClient) session.getAttribute("CLIENT");
instructionStreamLock = (ReentrantLock) session.getAttribute("INSTRUCTION_STREAM_LOCK"); instructionStreamLock = (ReentrantLock) session.getAttribute("INSTRUCTION_STREAM_LOCK");

View File

@@ -1,8 +1,9 @@
package net.sourceforge.guacamole.net; package net.sourceforge.guacamole.net.authentication;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
import net.sourceforge.guacamole.GuacamoleException; import net.sourceforge.guacamole.GuacamoleException;
import net.sourceforge.guacamole.net.GuacamoleSession;
/* /*
* Guacamole - Clientless Remote Desktop * Guacamole - Clientless Remote Desktop

View File

@@ -1,8 +1,9 @@
package net.sourceforge.guacamole.net; package net.sourceforge.guacamole.net.authentication;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
import net.sourceforge.guacamole.GuacamoleException; import net.sourceforge.guacamole.GuacamoleException;
import net.sourceforge.guacamole.net.GuacamoleSession;
/* /*
* Guacamole - Clientless Remote Desktop * Guacamole - Clientless Remote Desktop

View File

@@ -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<String, AuthInfo> 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<String, AuthInfo> authMapping = new HashMap<String, AuthInfo>();
public Map<String, AuthInfo> 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;
}
}
}
}

View File

@@ -1,10 +1,10 @@
package net.sourceforge.guacamole.basic; package net.sourceforge.guacamole.net.authentication.basic;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
import net.sourceforge.guacamole.GuacamoleException; import net.sourceforge.guacamole.GuacamoleException;
import net.sourceforge.guacamole.net.GuacamoleSession; import net.sourceforge.guacamole.net.GuacamoleSession;
import net.sourceforge.guacamole.net.GuacamoleSessionProvider; import net.sourceforge.guacamole.net.authentication.GuacamoleSessionProvider;
/* /*
* Guacamole - Clientless Remote Desktop * Guacamole - Clientless Remote Desktop

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Context antiJARLocking="true" path=""/>

View File

@@ -17,18 +17,15 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
--> -->
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- Basic config --> <!-- Basic config -->
<welcome-file-list> <welcome-file-list>
<welcome-file>index.html</welcome-file> <welcome-file>index.html</welcome-file>
</welcome-file-list> </welcome-file-list>
<session-config> <session-config>
<session-timeout> <session-timeout>
30 30
</session-timeout> </session-timeout>
</session-config> </session-config>
<!-- Guacamole Tunnel Servlets --> <!-- Guacamole Tunnel Servlets -->
<servlet> <servlet>
<description>Connect servlet.</description> <description>Connect servlet.</description>
@@ -57,15 +54,13 @@
<servlet-name>Inbound</servlet-name> <servlet-name>Inbound</servlet-name>
<url-pattern>/inbound</url-pattern> <url-pattern>/inbound</url-pattern>
</servlet-mapping> </servlet-mapping>
<!-- Basic Login Servlets --> <!-- Basic Login Servlets -->
<servlet> <servlet>
<servlet-name>BasicLogin</servlet-name> <servlet-name>BasicLogin</servlet-name>
<servlet-class>net.sourceforge.guacamole.basic.BasicLogin</servlet-class> <servlet-class>net.sourceforge.guacamole.net.authentication.basic.BasicLogin</servlet-class>
</servlet> </servlet>
<servlet-mapping> <servlet-mapping>
<servlet-name>BasicLogin</servlet-name> <servlet-name>BasicLogin</servlet-name>
<url-pattern>/login</url-pattern> <url-pattern>/login</url-pattern>
</servlet-mapping> </servlet-mapping>
</web-app> </web-app>