GUACAMOLE-197: Add some comments to document the logic and the functions.

This commit is contained in:
Nick Couchman
2017-02-05 20:24:14 -05:00
committed by Nick Couchman
parent efad91adb0
commit 731c622e8f
4 changed files with 108 additions and 3 deletions

View File

@@ -90,7 +90,7 @@ public class AuthenticationProviderService {
public AuthenticatedUser authenticateUser(Credentials credentials)
throws GuacamoleException {
// Attempt bind
// Initialize Radius Packet and try to authenticate
RadiusPacket radPack;
try {
radPack = radiusService.authenticate(credentials.getUsername(),
@@ -107,10 +107,17 @@ public class AuthenticationProviderService {
logger.debug("Nothing in the RADIUS packet.");
throw new GuacamoleInvalidCredentialsException("Permission denied.", CredentialsInfo.USERNAME_PASSWORD);
}
// If we get back an AccessReject packet, login is denied.
else if (radPack instanceof AccessReject) {
logger.debug("Login has been rejected by RADIUS server.");
throw new GuacamoleInvalidCredentialsException("Permission denied.", CredentialsInfo.USERNAME_PASSWORD);
}
/**
* If we receive an AccessChallenge package, the server needs more information -
* We create a new form/field with the challenge message.
*/
else if (radPack instanceof AccessChallenge) {
try {
String replyMsg = radPack.getAttributeValue("Reply-Message").toString();
@@ -127,6 +134,8 @@ public class AuthenticationProviderService {
throw new GuacamoleInvalidCredentialsException("Authentication error.", CredentialsInfo.USERNAME_PASSWORD);
}
}
// If we receive AccessAccept, authentication has succeeded
else if (radPack instanceof AccessAccept) {
try {
@@ -139,6 +148,8 @@ public class AuthenticationProviderService {
radiusService.disconnect();
}
}
// Something else we haven't thought of has happened, so we throw an error
else
throw new GuacamoleInvalidCredentialsException("Unknown error trying to authenticate.", CredentialsInfo.USERNAME_PASSWORD);

View File

@@ -128,6 +128,17 @@ public class ConfigurationService {
);
}
/**
* Returns the number of retries for connecting to the RADIUS server
* from guacamole.properties.
*
* @return
* The number of retries for connection to the RADIUS server,
* from guacamole.properties.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public int getRadiusRetries() throws GuacamoleException {
return environment.getProperty(
RadiusGuacamoleProperties.RADIUS_RETRIES,
@@ -135,6 +146,17 @@ public class ConfigurationService {
);
}
/**
* Returns the timeout for connecting to the RADIUS server
* from guacamole.properties.
*
* @return
* The timeout for connection to the RADIUS server,
* from guacamole.properties.
*
* @throws GuacamoleException
* If guacamole.properties cannot be parsed.
*/
public int getRadiusTimeout() throws GuacamoleException {
return environment.getProperty(
RadiusGuacamoleProperties.RADIUS_TIMEOUT,

View File

@@ -77,6 +77,7 @@ public class RadiusConnectionService {
private void createRadiusConnection() {
/*
* This is commented out right now because it isn't implemented, yet.
// Map encryption method to proper connection and socket factory
EncryptionMethod encryptionMethod = confService.getEncryptionMethod();
switch (encryptionMethod) {
@@ -101,6 +102,8 @@ public class RadiusConnectionService {
}
*/
// Create the RADIUS client with the configuration parameters
try {
radiusClient = new RadiusClient(InetAddress.getByName(confService.getRadiusServer()),
confService.getRadiusSharedSecret(),
@@ -126,27 +129,50 @@ public class RadiusConnectionService {
}
/**
* Authenticate to the RADIUS server and return the response from the
* server.
*
* @param username
* The username for authentication.
* @param password
* The password for authentication.
*
* @return
* A RadiusPacket with the response of the server.
*
* @throws GuacamoleException
* If an error occurs while talking to the server.
*/
public RadiusPacket authenticate(String username, String password)
throws GuacamoleException {
// Create the connection and load the attribute dictionary
createRadiusConnection();
AttributeFactory.loadAttributeDictionary("net.jradius.dictionary.AttributeDictionaryImpl");
// If the client is null, we return null - something has gone wrong
if (radiusClient == null)
return null;
// If a username hasn't been provided, stop
if (username == null || username.isEmpty()) {
logger.warn("Anonymous access not allowed with RADIUS client.");
return null;
}
// If a password hasn't been provided, stop
if (password == null || password.isEmpty()) {
logger.warn("Password required for RADIUS authentication.");
return null;
}
// Set up the authentication protocol as configured
RadiusAuthenticator radAuth = radiusClient.getAuthProtocol(confService.getRadiusAuthProtocol());
if (radAuth == null)
throw new GuacamoleException("Unknown RADIUS authentication protocol.");
// Set up attributes, create the access request, and send the packet
try {
AttributeList radAttrs = new AttributeList();
radAttrs.add(new Attr_UserName(username));
@@ -157,11 +183,13 @@ public class RadiusConnectionService {
radAuth.processRequest(radAcc);
return radiusClient.sendReceive(radAcc, confService.getRadiusRetries());
}
catch (RadiusException e) {
logger.error("Unable to complete authentication.", e.getMessage());
logger.debug("Authentication with RADIUS failed.", e);
return null;
}
catch (NoSuchAlgorithmException e) {
logger.error("No such RADIUS algorithm: {}", e.getMessage());
logger.debug("Unknown RADIUS algorithm.", e);
@@ -169,28 +197,56 @@ public class RadiusConnectionService {
}
}
/**
* Authenticate to the RADIUS server using existing state and a response
*
* @param username
* The username for the authentication
* @param state
* The previous state of the RADIUS connection
* @param response
* The response to the RADIUS challenge
*
* @return
* A RadiusPacket with the response of the server.
*
* @throws GuacamoleException
* If an error occurs while talking to the server.
*/
public RadiusPacket authenticate(String username, String state, String response)
throws GuacamoleException {
// Create the RADIUS connection and set up the dictionary
createRadiusConnection();
AttributeFactory.loadAttributeDictionary("net.jradius.dictionary.AttributeDictionaryImpl");
// Client failed to set up, so we return null
if (radiusClient == null)
return null;
// If a username wasn't passed, we quit
if (username == null || username.isEmpty()) {
logger.warn("Anonymous access not allowed with RADIUS client.");
return null;
}
// If the state wasn't passed, we quit
if (state == null || state.isEmpty()) {
logger.warn("This method needs a previous RADIUS state to respond to.");
return null;
}
// If the response wasn't passed, we quit
if (response == null || response.isEmpty()) {
logger.warn("Response required for RADIUS authentication.");
return null;
}
/**
* Set up the authenticator based on the configured protocol.
* Unless that fails, add the attributes to the packet, set up the packet
* and send the packet.
*/
RadiusAuthenticator radAuth = radiusClient.getAuthProtocol(confService.getRadiusAuthProtocol());
if (radAuth == null)
throw new GuacamoleException("Unknown RADIUS authentication protocol.");
@@ -221,8 +277,6 @@ public class RadiusConnectionService {
* Disconnects the given RADIUS connection, logging any failure to do so
* appropriately.
*
* @param radiusConnection
* The RADIUS connection to disconnect.
*/
public void disconnect() {

View File

@@ -31,11 +31,29 @@ public class RadiusChallengeResponseField extends Field {
*/
private final Logger logger = LoggerFactory.getLogger(RadiusChallengeResponseField.class);
/**
* The field returned by the RADIUS challenge/response.
*/
private static final String RADIUS_FIELD_NAME = "guac-radius-challenge-response";
/**
* The type of field to initialize for the challenge/response.
*/
private static final String RADIUS_FIELD_TYPE = "GUAC_RADIUS_CHALLENGE_RESPONSE";
/**
* The state of the connection passed by the previous RADIUS attempt.
*/
private final String radiusState;
/**
* The message the RADIUS server sent back in the challenge.
*/
private final String replyMsg;
/**
* Initialize the field with the reply message and the state.
*/
public RadiusChallengeResponseField(String replyMsg, String radiusState) {
super(RADIUS_FIELD_NAME, RADIUS_FIELD_TYPE);
logger.debug("Initializing the RADIUS challenge/response field: {}", replyMsg);