/support/cas-server-support-radius-core/src/main/java/org/apereo/cas/adaptors/radius/server/AbstractRadiusServer.java

https://github.com/frett/cas · Java · 195 lines · 135 code · 26 blank · 34 comment · 19 complexity · 6102ca79247e84439c13c5fcceabf126 MD5 · raw file

  1. package org.apereo.cas.adaptors.radius.server;
  2. import org.apereo.cas.adaptors.radius.CasRadiusResponse;
  3. import org.apereo.cas.adaptors.radius.RadiusClientFactory;
  4. import org.apereo.cas.adaptors.radius.RadiusProtocol;
  5. import org.apereo.cas.adaptors.radius.RadiusServer;
  6. import lombok.Getter;
  7. import lombok.ToString;
  8. import lombok.extern.slf4j.Slf4j;
  9. import lombok.val;
  10. import net.jradius.client.RadiusClient;
  11. import net.jradius.client.auth.RadiusAuthenticator;
  12. import net.jradius.dictionary.Attr_ClientIPAddress;
  13. import net.jradius.dictionary.Attr_NASIPAddress;
  14. import net.jradius.dictionary.Attr_NASIPv6Address;
  15. import net.jradius.dictionary.Attr_NASIdentifier;
  16. import net.jradius.dictionary.Attr_NASPort;
  17. import net.jradius.dictionary.Attr_NASPortId;
  18. import net.jradius.dictionary.Attr_NASPortType;
  19. import net.jradius.dictionary.Attr_State;
  20. import net.jradius.dictionary.Attr_UserName;
  21. import net.jradius.dictionary.Attr_UserPassword;
  22. import net.jradius.dictionary.vsa_redback.Attr_NASRealPort;
  23. import net.jradius.packet.AccessAccept;
  24. import net.jradius.packet.AccessChallenge;
  25. import net.jradius.packet.AccessRequest;
  26. import net.jradius.packet.RadiusResponse;
  27. import net.jradius.packet.attribute.AttributeFactory;
  28. import net.jradius.packet.attribute.AttributeList;
  29. import org.apache.commons.lang3.StringUtils;
  30. import org.apereo.inspektr.common.web.ClientInfoHolder;
  31. import org.bouncycastle.jce.provider.BouncyCastleProvider;
  32. import java.io.Serializable;
  33. import java.security.Security;
  34. import java.util.Optional;
  35. /**
  36. * Implementation of a RadiusServer that utilizes the JRadius packages available
  37. * at <a href="http://jradius.sf.net">http://jradius.sf.net</a>.
  38. *
  39. * @author Scott Battaglia
  40. * @author Marvin S. Addison
  41. * @author Misagh Moayyed
  42. * @since 3.1
  43. */
  44. @Slf4j
  45. @ToString
  46. @Getter
  47. public abstract class AbstractRadiusServer implements RadiusServer {
  48. /**
  49. * Default retry count, {@value}.
  50. **/
  51. public static final int DEFAULT_RETRY_COUNT = 3;
  52. private static final long serialVersionUID = -7122734096722096617L;
  53. static {
  54. AttributeFactory.loadAttributeDictionary("net.jradius.dictionary.AttributeDictionaryImpl");
  55. Security.addProvider(new BouncyCastleProvider());
  56. }
  57. /**
  58. * RADIUS protocol.
  59. */
  60. private final RadiusProtocol protocol;
  61. /**
  62. * Produces RADIUS client instances for authentication.
  63. */
  64. private final RadiusClientFactory radiusClientFactory;
  65. private final String nasIpAddress;
  66. private final String nasIpv6Address;
  67. private final String nasIdentifier;
  68. /**
  69. * Number of times to retry authentication when no response is received.
  70. */
  71. private final int retries;
  72. private final long nasPort;
  73. private final long nasPortId;
  74. private final long nasRealPort;
  75. private final long nasPortType;
  76. public AbstractRadiusServer(final RadiusProtocol protocol, final RadiusClientFactory radiusClientFactory) {
  77. this(protocol, radiusClientFactory, 1, null,
  78. null, -1, -1, null, -1, -1);
  79. }
  80. public AbstractRadiusServer(final RadiusProtocol protocol, final RadiusClientFactory clientFactory, final int retries,
  81. final String nasIpAddress, final String nasIpv6Address, final long nasPort, final long nasPortId,
  82. final String nasIdentifier, final long nasRealPort, final long nasPortType) {
  83. this.protocol = protocol;
  84. this.radiusClientFactory = clientFactory;
  85. this.retries = retries;
  86. this.nasIpAddress = nasIpAddress;
  87. this.nasIpv6Address = nasIpv6Address;
  88. this.nasPort = nasPort;
  89. this.nasPortId = nasPortId;
  90. this.nasIdentifier = nasIdentifier;
  91. this.nasRealPort = nasRealPort;
  92. this.nasPortType = nasPortType;
  93. }
  94. @Override
  95. public final CasRadiusResponse authenticate(final String username, final String password, final Optional state) throws Exception {
  96. val attributeList = new AttributeList();
  97. if (StringUtils.isNotBlank(username)) {
  98. attributeList.add(new Attr_UserName(username));
  99. }
  100. if (StringUtils.isNotBlank(password)) {
  101. attributeList.add(new Attr_UserPassword(password));
  102. }
  103. val clientInfo = ClientInfoHolder.getClientInfo();
  104. if (clientInfo != null) {
  105. val clientIpAddress = clientInfo.getClientIpAddress();
  106. val clientIpAttribute = new Attr_ClientIPAddress(clientIpAddress);
  107. LOGGER.debug("Adding client IP address attribute [{}]", clientIpAttribute);
  108. attributeList.add(clientIpAttribute);
  109. }
  110. state.ifPresent(value -> attributeList.add(new Attr_State(Serializable.class.cast(value))));
  111. if (StringUtils.isNotBlank(this.nasIpAddress)) {
  112. attributeList.add(new Attr_NASIPAddress(this.nasIpAddress));
  113. }
  114. if (StringUtils.isNotBlank(this.nasIpv6Address)) {
  115. attributeList.add(new Attr_NASIPv6Address(this.nasIpv6Address));
  116. }
  117. if (this.nasPort != -1) {
  118. attributeList.add(new Attr_NASPort(this.nasPort));
  119. }
  120. if (this.nasPortId != -1) {
  121. attributeList.add(new Attr_NASPortId(this.nasPortId));
  122. }
  123. if (StringUtils.isNotBlank(this.nasIdentifier)) {
  124. attributeList.add(new Attr_NASIdentifier(this.nasIdentifier));
  125. }
  126. if (this.nasRealPort != -1) {
  127. attributeList.add(new Attr_NASRealPort(this.nasRealPort));
  128. }
  129. if (this.nasPortType != -1) {
  130. attributeList.add(new Attr_NASPortType(this.nasPortType));
  131. }
  132. val client = this.radiusClientFactory.newInstance();
  133. try {
  134. val request = new AccessRequest(client, attributeList);
  135. LOGGER.debug("RADIUS access request prepared as [{}]", request.toString(true, true));
  136. val response = authenticateRequest(client, request);
  137. LOGGER.debug("RADIUS response from [{}]: [{}] as [{}]", client.getRemoteInetAddress().getCanonicalHostName(),
  138. response.getClass().getName(), response.toString(true, true));
  139. if (response instanceof AccessAccept || response instanceof AccessChallenge) {
  140. val attributes = response.getAttributes().getAttributeList();
  141. LOGGER.debug("Radius response code [{}] accepted with attributes [{}] and identifier [{}]", response.getCode(), attributes, response.getIdentifier());
  142. return new CasRadiusResponse(response.getCode(), response.getIdentifier(), attributes);
  143. }
  144. LOGGER.warn("Response is not recognized");
  145. } finally {
  146. if (client != null) {
  147. client.close();
  148. }
  149. }
  150. return null;
  151. }
  152. /**
  153. * Gets radius authenticator.
  154. *
  155. * @return the radius authenticator
  156. */
  157. public RadiusAuthenticator getRadiusAuthenticator() {
  158. return RadiusClient.getAuthProtocol(this.protocol.getName());
  159. }
  160. /**
  161. * Authenticate request and produce a response.
  162. *
  163. * @param client the client
  164. * @param accessRequest the access request
  165. * @return the radius response
  166. * @throws Exception the exception
  167. */
  168. protected abstract RadiusResponse authenticateRequest(RadiusClient client, AccessRequest accessRequest) throws Exception;
  169. }