diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java index c8a21d6a1..0f5dcf646 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/RadiusConnectionService.java @@ -44,7 +44,6 @@ import net.jradius.packet.attribute.AttributeList; import net.jradius.client.auth.EAPTLSAuthenticator; import net.jradius.client.auth.EAPTTLSAuthenticator; import net.jradius.client.auth.RadiusAuthenticator; -import net.jradius.client.auth.PEAPAuthenticator; import net.jradius.packet.attribute.AttributeFactory; import net.jradius.packet.AccessChallenge; import net.jradius.packet.RadiusResponse; @@ -99,74 +98,57 @@ public class RadiusConnectionService { } /** - * Creates a new instance of RadiusAuthentictor, configured with + * Creates a new instance of RadiusAuthenticator, configured with * parameters specified within guacamole.properties. * - * @param radiusClient - * A RadiusClient instance that has been initialized to - * communicate with a RADIUS server. - * * @return * A new RadiusAuthenticator instance which has been configured - * with parameters from guacamole.properties, or null if - * configuration fails. + * with parameters from guacamole.properties. * * @throws GuacamoleException * If the configuration cannot be read or the inner protocol is * not configured when the client is set up for a tunneled * RADIUS connection. */ - private RadiusAuthenticator setupRadiusAuthenticator( - RadiusClient radiusClient) throws GuacamoleException { + private RadiusAuthenticator getRadiusAuthenticator() throws GuacamoleException { - // If we don't have a radiusClient object, yet, don't go any further. - if (radiusClient == null) { - logger.error("RADIUS client hasn't been set up, yet."); - logger.debug("We can't run this method until the RADIUS client has been set up."); - return null; - } - - RadiusAuthenticator radAuth = radiusClient.getAuthProtocol( - confService.getRadiusAuthProtocol().toString()); - - if (radAuth == null) - throw new GuacamoleException("Could not get a valid RadiusAuthenticator for specified protocol: " + confService.getRadiusAuthProtocol()); + RadiusAuthenticator radAuth = confService.getRadiusAuthProtocol().getAuthenticator(); // If we're using any of the TLS protocols, we need to configure them - if (radAuth instanceof PEAPAuthenticator || - radAuth instanceof EAPTLSAuthenticator || - radAuth instanceof EAPTTLSAuthenticator) { + if (radAuth instanceof EAPTLSAuthenticator) { - // Pull TLS configuration parameters from guacamole.properties + EAPTLSAuthenticator tlsAuth = (EAPTLSAuthenticator) radAuth; + + // If provided, use the configured certificate authority for + // validating the connection to the RADIUS server File caFile = confService.getRadiusCAFile(); - String caPassword = confService.getRadiusCAPassword(); - File keyFile = confService.getRadiusKeyFile(); - String keyPassword = confService.getRadiusKeyPassword(); - if (caFile != null) { - ((EAPTLSAuthenticator)radAuth).setCaFile(caFile.toString()); - ((EAPTLSAuthenticator)radAuth).setCaFileType(confService.getRadiusCAType()); + tlsAuth.setCaFile(caFile.toString()); + tlsAuth.setCaFileType(confService.getRadiusCAType()); + String caPassword = confService.getRadiusCAPassword(); if (caPassword != null) - ((EAPTLSAuthenticator)radAuth).setCaPassword(caPassword); + tlsAuth.setCaPassword(caPassword); } + // Use configured password for unlocking the RADIUS private key, + // if specified + String keyPassword = confService.getRadiusKeyPassword(); if (keyPassword != null) - ((EAPTLSAuthenticator)radAuth).setKeyPassword(keyPassword); + tlsAuth.setKeyPassword(keyPassword); + + // Use configured RADIUS certificate and private key (always + // required for TLS-based protocols) + File keyFile = confService.getRadiusKeyFile(); + tlsAuth.setKeyFile(keyFile.toString()); + tlsAuth.setKeyFileType(confService.getRadiusKeyType()); + tlsAuth.setTrustAll(confService.getRadiusTrustAll()); - ((EAPTLSAuthenticator)radAuth).setKeyFile(keyFile.toString()); - ((EAPTLSAuthenticator)radAuth).setKeyFileType(confService.getRadiusKeyType()); - ((EAPTLSAuthenticator)radAuth).setTrustAll(confService.getRadiusTrustAll()); } // If we're using EAP-TTLS, we need to define tunneled protocol if (radAuth instanceof EAPTTLSAuthenticator) { - RadiusAuthenticationProtocol innerProtocol = - confService.getRadiusEAPTTLSInnerProtocol(); - - if (innerProtocol == null) - throw new GuacamoleException("Missing or invalid inner protocol for EAP-TTLS."); - - ((EAPTTLSAuthenticator)radAuth).setInnerProtocol(innerProtocol.toString()); + RadiusAuthenticationProtocol innerProtocol = confService.getRadiusEAPTTLSInnerProtocol(); + ((EAPTTLSAuthenticator)radAuth).setInnerProtocol(innerProtocol.JRADIUS_PROTOCOL_NAME); } return radAuth; @@ -211,14 +193,8 @@ public class RadiusConnectionService { RadiusClient radiusClient = createRadiusConnection(); AttributeFactory.loadAttributeDictionary("net.jradius.dictionary.AttributeDictionaryImpl"); - // Client failed to set up, so we return null - if (radiusClient == null) - return null; - // Set up the RadiusAuthenticator - RadiusAuthenticator radAuth = setupRadiusAuthenticator(radiusClient); - if (radAuth == null) - throw new GuacamoleException("Unknown RADIUS authentication protocol."); + RadiusAuthenticator radAuth = getRadiusAuthenticator(); // Add attributes to the connection and send the packet try { diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/conf/ConfigurationService.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/conf/ConfigurationService.java index 2809f7c76..68ea6898e 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/conf/ConfigurationService.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/conf/ConfigurationService.java @@ -317,7 +317,7 @@ public class ConfigurationService { public RadiusAuthenticationProtocol getRadiusEAPTTLSInnerProtocol() throws GuacamoleException { - RadiusAuthenticationProtocol authProtocol = environment.getProperty( + RadiusAuthenticationProtocol authProtocol = environment.getRequiredProperty( RadiusGuacamoleProperties.RADIUS_EAP_TTLS_INNER_PROTOCOL ); diff --git a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/conf/RadiusAuthenticationProtocol.java b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/conf/RadiusAuthenticationProtocol.java index 7b995823a..4db295973 100644 --- a/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/conf/RadiusAuthenticationProtocol.java +++ b/extensions/guacamole-auth-radius/src/main/java/org/apache/guacamole/auth/radius/conf/RadiusAuthenticationProtocol.java @@ -19,6 +19,15 @@ package org.apache.guacamole.auth.radius.conf; +import net.jradius.client.RadiusClient; +import net.jradius.client.auth.CHAPAuthenticator; +import net.jradius.client.auth.EAPMD5Authenticator; +import net.jradius.client.auth.EAPTLSAuthenticator; +import net.jradius.client.auth.EAPTTLSAuthenticator; +import net.jradius.client.auth.MSCHAPv1Authenticator; +import net.jradius.client.auth.MSCHAPv2Authenticator; +import net.jradius.client.auth.PAPAuthenticator; +import net.jradius.client.auth.RadiusAuthenticator; import org.apache.guacamole.properties.EnumGuacamoleProperty.PropertyValue; /** @@ -31,42 +40,88 @@ public enum RadiusAuthenticationProtocol { * Password Authentication Protocol (PAP). */ @PropertyValue("pap") - PAP, + PAP(PAPAuthenticator.NAME), /** * Challenge-Handshake Authentication Protocol (CHAP). */ @PropertyValue("chap") - CHAP, + CHAP(CHAPAuthenticator.NAME), /** * Microsoft implementation of CHAP, Version 1 (MS-CHAPv1). */ @PropertyValue("mschapv1") - MSCHAP_V1, + MSCHAP_V1(MSCHAPv1Authenticator.NAME), /** * Microsoft implementation of CHAP, Version 2 (MS-CHAPv2). */ @PropertyValue("mschapv2") - MSCHAP_V2, + MSCHAP_V2(MSCHAPv2Authenticator.NAME), /** * Extensible Authentication Protocol (EAP) with MD5 Hashing (EAP-MD5). */ @PropertyValue("eap-md5") - EAP_MD5, + EAP_MD5(EAPMD5Authenticator.NAME), /** * Extensible Authentication Protocol (EAP) with TLS encryption (EAP-TLS). */ @PropertyValue("eap-tls") - EAP_TLS, + EAP_TLS(EAPTLSAuthenticator.NAME), /** * Extensible Authentication Protocol (EAP) with Tunneled TLS (EAP-TTLS). */ @PropertyValue("eap-ttls") - EAP_TTLS; + EAP_TTLS(EAPTTLSAuthenticator.NAME); + + /** + * The unique name of the JRadius {@link RadiusAuthenticator} that + * implements this protocol. + */ + public final String JRADIUS_PROTOCOL_NAME; + + /** + * Creates a new RadiusAuthenticationProtocol associated with the given + * JRadius protocol name. + * + * @param protocolName + * The unique name of the JRadius {@link RadiusAuthenticator} that + * implements this protocol. + */ + RadiusAuthenticationProtocol(String protocolName) { + this.JRADIUS_PROTOCOL_NAME = protocolName; + } + + /** + * Returns a new instance of the JRadius {@link RadiusAuthenticator} that + * implements this protocol. This function will never return null. + * + * @return + * A new instance of the JRadius {@link RadiusAuthenticator} that + * implements this protocol. + * + * @throws IllegalStateException + * If a bug within the JRadius library prevents retrieval of the + * authenticator for a protocol that is known to be supported. + */ + public RadiusAuthenticator getAuthenticator() throws IllegalStateException { + + // As we are using JRadius' own NAME constants for retrieving + // authenticator instances, the retrieval operation should always + // succeed except in the case of a bug within the JRadius library + RadiusAuthenticator authenticator = RadiusClient.getAuthProtocol(JRADIUS_PROTOCOL_NAME); + if (authenticator == null) + throw new IllegalStateException(String.format("JRadius failed " + +"to locate its own support for protocol \"%s\". This is " + + "likely a bug in the JRadius library.", + JRADIUS_PROTOCOL_NAME)); + + return authenticator; + + } }