* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import java.io.BufferedReader;
import net.sourceforge.guacamole.net.auth.AuthenticationProvider;
import java.io.File;
+import java.io.FileReader;
import java.io.IOException;
+import java.io.Reader;
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 net.sourceforge.guacamole.net.auth.UsernamePassword;
-import net.sourceforge.guacamole.net.basic.properties.BasicGuacamoleProperties;
+import net.sourceforge.guacamole.net.auth.Credentials;
+import net.sourceforge.guacamole.properties.FileGuacamoleProperty;
import net.sourceforge.guacamole.properties.GuacamoleProperties;
import net.sourceforge.guacamole.protocol.GuacamoleConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
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 AuthenticationProvider<UsernamePassword> {
+/**
+ * Authenticates users against a static list of username/password pairs.
+ * Each username/password may be associated with multiple configurations.
+ * This list is stored in an XML file which is reread if modified.
+ *
+ * This is modified version of BasicFileAuthenticationProvider written by Michael Jumper.
+ *
+ * @author Michal Kotas
+ */
+public class BasicFileAuthenticationProvider implements AuthenticationProvider {
private Logger logger = LoggerFactory.getLogger(BasicFileAuthenticationProvider.class);
private long mappingTime;
private Map<String, AuthInfo> mapping;
+ /**
+ * The filename of the XML file to read the user mapping from.
+ */
+ public static final FileGuacamoleProperty BASIC_USER_MAPPING = new FileGuacamoleProperty() {
+
+ @Override
+ public String getName() { return "basic-user-mapping"; }
+
+ };
+
private File getUserMappingFile() throws GuacamoleException {
// Get user mapping file
- return GuacamoleProperties.getProperty(BasicGuacamoleProperties.BASIC_USER_MAPPING);
+ return GuacamoleProperties.getProperty(BASIC_USER_MAPPING);
}
// Parse document
try {
+ // Set up parser
BasicUserMappingContentHandler contentHandler = new BasicUserMappingContentHandler();
XMLReader parser = XMLReaderFactory.createXMLReader();
parser.setContentHandler(contentHandler);
- parser.parse(mapFile.getAbsolutePath());
+ // Read and parse file
+ Reader reader = new BufferedReader(new FileReader(mapFile));
+ parser.parse(new InputSource(reader));
+ reader.close();
+
+ // Init mapping and record mod time of file
mappingTime = mapFile.lastModified();
mapping = contentHandler.getUserMapping();
}
@Override
- public Map<String, GuacamoleConfiguration> getAuthorizedConfigurations(UsernamePassword credentials) throws GuacamoleException {
+ public Map<String, GuacamoleConfiguration> getAuthorizedConfigurations(Credentials credentials) throws GuacamoleException {
// Check mapping file mod time
File userMappingFile = getUserMappingFile();
if (mapping == null)
throw new GuacamoleException("User mapping could not be read.");
- Map<String, GuacamoleConfiguration> configs = new HashMap<String, GuacamoleConfiguration>();
-
// Validate and return info for given user and pass
AuthInfo info = mapping.get(credentials.getUsername());
- if (info != null && info.validate(credentials.getUsername(), credentials.getPassword()))
- configs.put("DEFAULT", info.getConfiguration());
+ if (info != null && info.validate(credentials.getUsername(), credentials.getPassword())) {
+
+ //Map<String, GuacamoleConfiguration> configs = new HashMap<String, GuacamoleConfiguration>();
+ //configs.put("DEFAULT", info.getConfiguration());
+ //return configs;
+
+ Map<String, GuacamoleConfiguration> configs = info.getConfigurations();
+ return configs;
+ }
- return configs;
+ // Unauthorized
+ return null;
}
private String auth_password;
private Encoding auth_encoding;
- private GuacamoleConfiguration config;
+ private Map<String, GuacamoleConfiguration> configs;
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;
- config = new GuacamoleConfiguration();
+ configs = new HashMap<String, GuacamoleConfiguration>();
}
private static final char HEX_CHARS[] = {
}
- public GuacamoleConfiguration getConfiguration() {
- return config;
+ public GuacamoleConfiguration getConfiguration(String name) {
+ //return configs;
+ return configs.get(name);
+ }
+ public Map<String, GuacamoleConfiguration> getConfigurations() {
+ return configs;
+ }
+ public void addConfiguration(String name) {
+ configs.put(name, new GuacamoleConfiguration());
}
}
-
private static class BasicUserMappingContentHandler extends DefaultHandler {
private Map<String, AuthInfo> authMapping = new HashMap<String, AuthInfo>();
private enum State {
ROOT,
USER_MAPPING,
+ REMOTE_SERVER,
AUTH_INFO,
PROTOCOL,
PARAMETER,
private State state = State.ROOT;
private AuthInfo current = null;
private String currentParameter = null;
+ private String currentRemoteServer = null;
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
switch (state) {
- case USER_MAPPING:
+ case USER_MAPPING:
- if (localName.equals("user-mapping")) {
- state = State.END;
- return;
- }
+ if (localName.equals("user-mapping")) {
+ state = State.END;
+ return;
+ }
- break;
+ break;
- case AUTH_INFO:
+ case AUTH_INFO:
- if (localName.equals("authorize")) {
+ if (localName.equals("authorize")) {
- // Finalize mapping for this user
- authMapping.put(
- current.auth_username,
- current
- );
+ // Finalize mapping for this user
+ authMapping.put(
+ current.auth_username,
+ current
+ );
- state = State.USER_MAPPING;
- return;
- }
+ state = State.USER_MAPPING;
+ return;
+ }
- break;
+ break;
+
+ case REMOTE_SERVER:
- case PROTOCOL:
+ if (localName.equals("remote-server")) {
+ state = State.AUTH_INFO;
+ return;
+ }
- if (localName.equals("protocol")) {
- state = State.AUTH_INFO;
- return;
- }
+ break;
- break;
+ case PROTOCOL:
- case PARAMETER:
+ if (localName.equals("protocol")) {
+ state = State.REMOTE_SERVER;
+ return;
+ }
- if (localName.equals("param")) {
- state = State.AUTH_INFO;
- return;
- }
+ break;
- break;
+ case PARAMETER:
- }
+ if (localName.equals("param")) {
+ state = State.REMOTE_SERVER;
+ return;
+ }
+
+ break;
+
+ }
throw new SAXException("Tag not yet complete: " + localName);
break;
- // Only <authorize> tags allowed in main document
case USER_MAPPING:
if (localName.equals("authorize")) {
case AUTH_INFO:
+ if (localName.equals("remote-server")) {
+
+ currentRemoteServer = attributes.getValue("servername");
+ if (currentRemoteServer == null)
+ throw new SAXException("Attribute \"servername\" required for param tag.");
+
+ current.addConfiguration(currentRemoteServer);
+
+ // Next state
+ state = State.REMOTE_SERVER;
+ return;
+ }
+
+ break;
+
+ case REMOTE_SERVER:
+
if (localName.equals("protocol")) {
// Next state
state = State.PROTOCOL;
return;
}
- break;
+ break;
}
public void characters(char[] ch, int start, int length) throws SAXException {
String str = new String(ch, start, length);
+
switch (state) {
case PROTOCOL:
- current.getConfiguration()
- .setProtocol(str);
+ current.getConfiguration(currentRemoteServer)
+ .setProtocol(str);
return;
case PARAMETER:
- current.getConfiguration()
+ current.getConfiguration(currentRemoteServer)
.setParameter(currentParameter, str);
return;