README.md
openam-auth-radius
Open AM's Radius Feature-set Library
The code in this repo implements three distinct features that share code for speaking the RADIUS protocol. First, it holds a RADIUS authentication module enabling Open AM to act as a RADIUS client and delegate authentication to a remote RADIUS server. Second, it also holds a RADIUS server backed by Open AM's authentication chains and modules allowing other RADIUS clients to delegate authentication to Open AM. And third, it contains a RADIUS command line client called the ConsoleClient that allows for testing of a RADIUS authentication against a RADIUS server like Open AM. The jar that is generated by this module is executable and launches the ConsoleClient as is shown below.
Concerning incoming RADIUS requests leveraging authentication modules, some authentication modules clearly can not be used by RADIUS clients. Traditionally, authentication modules have dealt only with Http based client. But RADIUS represents a new and distinctly different type of client. For example, there is no mechanism in RADIUS for persisting content between sessions such as can be done with cookies on Http clients. Any module that depends on use of an HttpServletRequest or HttpServletResponse object without verifying that they actually have those objects will result in exceptions being thrown and all authentication attempts via that module to be rejected.
With careful crafting most modules should be able to adjust their feature set to support RADIUS clients in addition to Http clients albeit potentially with a smaller feature set for the former. This can be done by providing different templates and different flows through the module to remove those features that are not applicable or adapt them to the different interactions available to RADIUS clients.
Launching the Radius Server Feature
To use the RADIUS server functionality the following entry in Open AM's web.xml file kicks of loading of the RADIUS server features:
<listener>
<listener-class>com.sun.identity.authentication.modules.radius.server.config.ServletContextListenerLauncher
</listener-class>
</listener>
There is also support for launching via a SpringFramework component-scan directive in a servlet file if desired. The above web.xml declaration results in the following RADIUS server log entries appearing in catalina.out assuming a tomcat deployment. At startup you'll see these lines appear. Some parts have been snipped out in the content below to make it more clear:
26-Feb-2015 13:22:22.926 INFO [localhost-startStop-1] <snip/> ---> ServletContextListenerLauncher starting RadiusServiceStarter
26-Feb-2015 13:22:22.932 INFO [localhost-startStop-1] <snip/> Loaded OpenAM Authn Radius Module = built 2015-02-26 23:53 UTC
Enabling the Radius Server
Upon starting up, the RADIUS server functionality relies upon constructs in OpenAM's admin console for its configuration. If such are not found they are automatically added so that the server can obtain the default configuration and register for notification of changes by an administrator making adjustments in the admin console. If that auto-registration is necessary you will see it taking place in catalina.out with lines like these:
26-Feb-2015 13:29:20.198 INFO [RADIUS-RadiusServiceStarter] <snip/> RadiusServerService not found. Loading...
26-Feb-2015 13:29:20.201 INFO [RADIUS-RadiusServiceStarter] <snip/> Service Descriptor file for RadiusServerService
found at: jar:file:/Users/boydmr/tomcat8/apache-tomcat-8.0.9/webapps/sso/WEB-INF/lib/openam-auth-radius-1.0.1.jar!/RadiusServerService.xml
Immediately following these lines you'll then see the default configuration being loaded including what the current values are in very concise form. Similar lines to these will appear whenever Open AM starts up. Note that by default the RADIUS server is disabled.
26-Feb-2015 13:29:22.307 INFO [RADIUS-RadiusServiceStarter] <snip/> Loading RADIUS Config...
26-Feb-2015 13:29:22.361 INFO [RADIUS-RadiusServiceStarter] <snip/> --- Loaded Config ---
[RadiusServiceConfig NO 1812 P( 1, 10, 10, 10)]
26-Feb-2015 13:29:22.362 INFO [RADIUS-RadiusServiceStarter] <snip/> RADIUS service disabled.
This default configuration and the constructs for configuring these values in Open AM's admin console are defined by the RadiusServerService.xml file located the project source in the resources directory. You can view the RADIUS configuration constructs by going to the Configuration tab, the Global sub-tab, and selecting the RADIUS Server entry in the Global Properties table. Once in that page you can now define RADIUS Clients, set the port on which to listen for requests, and enable the RADIUS server.
Whenever this configuration for the RADIUS server changes you'll immediately see log entries in catalina.out that show the RADIUS server configuration being reloaded. For example, once radius is enabled the following log entries will appear indicating that the listener is active and information about the backing thread pool for connections:
26-Feb-2015 13:52:11.338 INFO [RADIUS-RadiusServiceStarter] <snip/> RADIUS Config Changed. Loading...
26-Feb-2015 13:52:11.339 INFO [RADIUS-RadiusServiceStarter] <snip/> --- Loaded Config ---
[RadiusServiceConfig YES 1812 P( 1, 10, 10, 10)]
26-Feb-2015 13:52:11.343 INFO [RADIUS-RadiusServiceStarter] <snip/> RADIUS service enabled. Starting Listener.
26-Feb-2015 13:52:11.355 INFO [RADIUS-1812-Listener] <snip/> RADIUS Listener is Active.
Port : 1812
Threads Core : 1
Threads Max : 10
Thread Keep-alive : 10 sec
Request Queue : 10
Note that when configuration changes the logging includes each client's configuration in a very concise form. If any RADIUS requests are received before any clients are configured or if the configured clients don't match the IP address of the incoming packets the RADIUS server will log the attempt and silently drop to packet as specified in the RFC like so:
27-Jan-2015 09:45:25.004 WARNING [RADIUS-1812-Listener] <snip/>
No Defined RADIUS Client matches IP address /127.0.0.1. Dropping request.
This log message is very useful in that it specifies the exact value of the client's IP address that must be specified in the client configuration page for packets from that client to be accepted for authentication. Once this IP address is specified for a defined client the packets are now accepted and authentication against modules in the client's specified chain will proceed.
Testing with ConsoleClient
To exercise the RADIUS server we can use this module's generated jar file to run the included ConsoleClient command line tool. It allows a user to authenticate to openAM using the RADIUS protocol by providing simple prompts on the command line and translating user input to corresponding requests to the server. To run this tool open a command shell that has access to java. Now change directory to be in the Open AM's WEB-INF/lib directory or include the full path to the module's jar file, such as openam-auth-radius-1.0.1.jar, in the following command for your current directory:
java -jar <path-to-jar>
When starting up it will print out its build information indicating its version and build date and then look for a radius.properties file in the current directory. If not found, as shown here, it will prompt the user to add a radius.properties file in the current directory with the indicated properties shown:
java -jar ~/tomcat8/apache-tomcat-8.0.9/webapps/sso/WEB-INF/lib/openam-auth-radius-1.0.1.jar
Feb 26, 2015 5:09:53 PM <snip/>
INFO: Loaded OpenAM Authn Radius Module = 1.0.1 built 2015-02-26 23:53 UTC
Missing required config file 'radius.properties' in current directory /Users/boydmr/.
Must Contain:
secret=<shared-secret-with-server>
host=<hostname-or-ip-address>
port=<port-on-target-host>
May Contain:
show-traffic=true
The shared secret must match exactly the value specified for the RADIUS Client configured in Open AM for this particular traffic. More on that in a minute. The host can be either a DNS name or an IP address and must resolve to the Open AM server or cluster. The port must match the port configured for the RADIUS server in openAM's console. For example, I'll create a radius.properties file with these values including telling the ConsoleClient to log the RADIUS traffic:
secret=letmein
host=127.0.0.1
port=1812
show-traffic=true
Once I have the radius.properties file defined the ConsoleClient will now prompt for Username and Password. This must be a user in OpenAM's backing user store. For my testing where I use embedded OpenDJ I used the admin console and created a user boydmr in the root realm.
Once username and password are entered the ConsoleClient will connect to the RADIUS server and attempt to authentication via username and password. As required in section 3 of RFC 2865 for this communication to be accepted by the RADIUS server the IP address of the incoming packet must match an IP address of a defined client or the packet will be dropped silently.
For example, I have not yet defined any clients in the admin console. So when ConstoleClient attempts to connect it hangs with this output after I enter my username and password:
java -jar ~/tomcat8/apache-tomcat-8.0.9/webapps/sso/WEB-INF/lib/openam-auth-radius-1.0.1.jar
Feb 26, 2015 2:08:26 PM <snip/>
INFO: Loaded OpenAM Authn Radius Module = 1.0.1 built 2015-02-26 23:53 UTC
? Username: boydmr
? Password: password
Packet To 127.0.0.1:1812
ACCESS_REQUEST [1]
- USER_NAME : boydmr
- USER_PASSWORD : *******
- NAS_IP_ADDRESS : localhost/127.0.0.1
- NAS_PORT : 0
The ConsoleClient hangs at this point and stops responding because it is waiting for a UDP response packet which will never come. This is clearly seen in the server side logs by the following log entry that results:
26-Feb-2015 17:39:37.254 WARNING [RADIUS-1812-Listener] <snip/>
No Defined RADIUS Client matches IP address /127.0.0.1. Dropping request.
The IP address listed in the log is what must be entered for the client before the server will accept packets from that client and not drop them. Hence, when configuring new clients it is very useful to first receive traffic from them to know what value to use when configuring that client.
Configuring a Radius Server Client
So I once again access the Radius Server configuration page in Open AM's console. But this time I press the New button in the Secondary Configuration Instance table. This lets me define a client allowed to connect to the Open AM RADIUS server port. Give the client a descriptive name. It is only used in the configuration page so it can be whatever helps us remember what remote client this configuration is for. The Client IP Address value must match that value that we saw in the log file /127.0.0.1 in this case. The Client Secret can be whatever you want it to be. A random one is generated for you and can be shared with the remote client out-of-band. Here, I set it to the same value that we have in out radius.properties file, letmein. I chose to enable traffic logging so that we can see how things look from the server's viewpoint. The handler class should be left alone but enables alternative implementations being plugged in. See the comments in the page for the interface to implement for such an attempt.
Finally, we come to Handler Class Configuration Properties. The OpenAMAuthHandler class expects two values:
realm = the name of a realm that contains the authentication chain to be used
chain = the name of the authentication chain to use
I chose to use the root realm and the default authentication chain created with a default Open AM configuration ldapService.
realm=/
chain=ldapService
Once I press the Add button I see the log output change indicating that the new configuration has been noticed and the RADIUS Server's Listener shut down and restarted with the new values.
26-Feb-2015 17:54:14.961 INFO [RADIUS-RadiusServiceStarter] com.sun.identity.authentication.modules.radius.server.config.RadiusServiceStarter.run RADIUS Config Changed. Loading...
26-Feb-2015 17:54:14.961 INFO [RADIUS-RadiusServiceStarter] com.sun.identity.authentication.modules.radius.server.config.RadiusServiceStarter.run --- Loaded Config ---
[RadiusServiceConfig YES 1812 P( 1, 10, 10, 10), C( /127.0.0.1=ConsoleClient test, letmein, true, com.sun.identity.authentication.modules.radius.server.spi.handlers.OpenAMAuthHandler, {realm=/, chain=ldapService})]
the packet is accepted by the server it will then attempt to authenticate the user via username and password. Hence, the first module in the chain specified for this client must use username and password for its callbacks.
If other modules are included in the chain then each field required by that module will be conveyed back to the ConsoleClient and it will prompt for each additional field. Once all have been entered then it will finish authentication against that module. This continues until the user fails to provide proper values required by each module in the chain or successfully authenticates to all modules in the chain.
As requests arrive at the Server log entries are made in catalina.out that can be used to troubleshoot problems with configuration.
If the RADIUS Client is not properly configured in the Server the incoming request will be seen and logged by the server but will be discarded. For example, suppose that I defined my client
Questions?
If you have questions send them to Mark Boyd at boydmr@ldschurch.org.