Implement multiple authorized connections per user.

This commit is contained in:
Michal Kotas
2012-04-18 12:01:34 -07:00
committed by Michael Jumper
parent b701b0e6b0
commit 5508a5b393
2 changed files with 111 additions and 53 deletions

View File

@@ -2,10 +2,15 @@
<!-- Per-user authentication and config information --> <!-- Per-user authentication and config information -->
<authorize username="USERNAME" password="PASSWORD"> <authorize username="USERNAME" password="PASSWORD">
<protocol>vnc</protocol>
<param name="hostname">localhost</param> <!-- Single authorized connection -->
<param name="port">5900</param> <remote-server servername="localhost">
<param name="password">VNCPASS</param> <protocol>vnc</protocol>
<param name="hostname">localhost</param>
<param name="port">5900</param>
<param name="password">VNCPASS</param>
</remote-server>
</authorize> </authorize>
<!-- Another user, but using md5 to hash the password <!-- Another user, but using md5 to hash the password
@@ -14,10 +19,23 @@
username="USERNAME2" username="USERNAME2"
password="319f4d26e3c536b5dd871bb2c52e3178" password="319f4d26e3c536b5dd871bb2c52e3178"
encoding="md5"> encoding="md5">
<protocol>vnc</protocol>
<param name="hostname">localhost</param> <!-- First authorized connection -->
<param name="port">5901</param> <remote-server servername="localhost">
<param name="password">VNCPASS</param> <protocol>vnc</protocol>
</authorize> <param name="hostname">localhost</param>
<param name="port">5901</param>
<param name="password">VNCPASS</param>
</remote-server>
<!-- Second authorized connection -->
<remote-server servername="otherhost">
<protocol>vnc</protocol>
<param name="hostname">otherhost</param>
<param name="port">5900</param>
<param name="password">VNCPASS</param>
</remote-server>
</authorize>
</user-mapping> </user-mapping>

View File

@@ -46,10 +46,12 @@ import org.xml.sax.helpers.XMLReaderFactory;
/** /**
* Authenticates users against a static list of username/password pairs. * Authenticates users against a static list of username/password pairs.
* Each username/password may be associated with exactly one configuration. * Each username/password may be associated with multiple configurations.
* This list is stored in an XML file which is reread if modified. * This list is stored in an XML file which is reread if modified.
* *
* @author Michael Jumper * This is modified version of BasicFileAuthenticationProvider written by Michael Jumper.
*
* @author Michal Kotas
*/ */
public class BasicFileAuthenticationProvider implements AuthenticationProvider { public class BasicFileAuthenticationProvider implements AuthenticationProvider {
@@ -136,8 +138,12 @@ public class BasicFileAuthenticationProvider implements AuthenticationProvider {
// Validate and return info for given user and pass // Validate and return info for given user and pass
AuthInfo info = mapping.get(credentials.getUsername()); AuthInfo info = mapping.get(credentials.getUsername());
if (info != null && info.validate(credentials.getUsername(), credentials.getPassword())) { if (info != null && info.validate(credentials.getUsername(), credentials.getPassword())) {
Map<String, GuacamoleConfiguration> configs = new HashMap<String, GuacamoleConfiguration>();
configs.put("DEFAULT", info.getConfiguration()); //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;
} }
@@ -157,14 +163,14 @@ public class BasicFileAuthenticationProvider implements AuthenticationProvider {
private String auth_password; private String auth_password;
private Encoding auth_encoding; private Encoding auth_encoding;
private GuacamoleConfiguration config; private Map<String, GuacamoleConfiguration> configs;
public AuthInfo(String auth_username, String auth_password, Encoding auth_encoding) { public AuthInfo(String auth_username, String auth_password, Encoding auth_encoding) {
this.auth_username = auth_username; this.auth_username = auth_username;
this.auth_password = auth_password; this.auth_password = auth_password;
this.auth_encoding = auth_encoding; this.auth_encoding = auth_encoding;
config = new GuacamoleConfiguration(); configs = new HashMap<String, GuacamoleConfiguration>();
} }
private static final char HEX_CHARS[] = { private static final char HEX_CHARS[] = {
@@ -220,13 +226,19 @@ public class BasicFileAuthenticationProvider implements AuthenticationProvider {
} }
public GuacamoleConfiguration getConfiguration() { public GuacamoleConfiguration getConfiguration(String name) {
return config; //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 static class BasicUserMappingContentHandler extends DefaultHandler {
private Map<String, AuthInfo> authMapping = new HashMap<String, AuthInfo>(); private Map<String, AuthInfo> authMapping = new HashMap<String, AuthInfo>();
@@ -238,6 +250,7 @@ public class BasicFileAuthenticationProvider implements AuthenticationProvider {
private enum State { private enum State {
ROOT, ROOT,
USER_MAPPING, USER_MAPPING,
REMOTE_SERVER,
AUTH_INFO, AUTH_INFO,
PROTOCOL, PROTOCOL,
PARAMETER, PARAMETER,
@@ -247,56 +260,66 @@ public class BasicFileAuthenticationProvider implements AuthenticationProvider {
private State state = State.ROOT; private State state = State.ROOT;
private AuthInfo current = null; private AuthInfo current = null;
private String currentParameter = null; private String currentParameter = null;
private String currentRemoteServer = null;
@Override @Override
public void endElement(String uri, String localName, String qName) throws SAXException { public void endElement(String uri, String localName, String qName) throws SAXException {
switch (state) { switch (state) {
case USER_MAPPING: case USER_MAPPING:
if (localName.equals("user-mapping")) { if (localName.equals("user-mapping")) {
state = State.END; state = State.END;
return; return;
} }
break; break;
case AUTH_INFO: case AUTH_INFO:
if (localName.equals("authorize")) { if (localName.equals("authorize")) {
// Finalize mapping for this user // Finalize mapping for this user
authMapping.put( authMapping.put(
current.auth_username, current.auth_username,
current current
); );
state = State.USER_MAPPING; state = State.USER_MAPPING;
return; return;
} }
break; break;
case REMOTE_SERVER:
case PROTOCOL: if (localName.equals("remote-server")) {
state = State.AUTH_INFO;
return;
}
if (localName.equals("protocol")) { break;
state = State.AUTH_INFO;
return;
}
break; case PROTOCOL:
case PARAMETER: if (localName.equals("protocol")) {
state = State.REMOTE_SERVER;
return;
}
if (localName.equals("param")) { break;
state = State.AUTH_INFO;
return;
}
break; case PARAMETER:
} if (localName.equals("param")) {
state = State.REMOTE_SERVER;
return;
}
break;
}
throw new SAXException("Tag not yet complete: " + localName); throw new SAXException("Tag not yet complete: " + localName);
@@ -317,7 +340,6 @@ public class BasicFileAuthenticationProvider implements AuthenticationProvider {
break; break;
// Only <authorize> tags allowed in main document
case USER_MAPPING: case USER_MAPPING:
if (localName.equals("authorize")) { if (localName.equals("authorize")) {
@@ -349,6 +371,23 @@ public class BasicFileAuthenticationProvider implements AuthenticationProvider {
case AUTH_INFO: 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")) { if (localName.equals("protocol")) {
// Next state // Next state
state = State.PROTOCOL; state = State.PROTOCOL;
@@ -366,7 +405,7 @@ public class BasicFileAuthenticationProvider implements AuthenticationProvider {
return; return;
} }
break; break;
} }
@@ -378,15 +417,16 @@ public class BasicFileAuthenticationProvider implements AuthenticationProvider {
public void characters(char[] ch, int start, int length) throws SAXException { public void characters(char[] ch, int start, int length) throws SAXException {
String str = new String(ch, start, length); String str = new String(ch, start, length);
switch (state) { switch (state) {
case PROTOCOL: case PROTOCOL:
current.getConfiguration() current.getConfiguration(currentRemoteServer)
.setProtocol(str); .setProtocol(str);
return; return;
case PARAMETER: case PARAMETER:
current.getConfiguration() current.getConfiguration(currentRemoteServer)
.setParameter(currentParameter, str); .setParameter(currentParameter, str);
return; return;