JRadius provides a full-featured Java RADIUS Client. Utilizing the same attribute dictionary used by the JRadius Server, the JRadius Client API provides an easy to use and highly versatile RADIUS client. The client and server portions of JRadius use the same code-base and dictionary, but one does not require the use of the other. Meaning, to use the client, you do not have to use the server, and visa versa. The following is a simple example of using the JRadius Client API in a Java application.
Before using the JRadius library, a JRadius dictionary should be loaded. Above, the default JRadius dictionary is being loaded (recommended), but a more minimal dictionary can also be built. To begin a client session, instantiate the RadiusClient context as follows:
RadiusClient radiusClient = new RadiusClient( inetAddress, // InetAddress - Address of remote RADIUS Server sharedSecret); // String - Shared Secret for remote RADIUS Server
Since we will be sending many of the same attributes in the authentication and accounting packets, it is convenient to build an AttributeList to be included in multiple packets.
AttributeList attributeList = new AttributeList(); attributeList.add(new Attr_UserName("test")); attributeList.add(new Attr_NASPortType(Attr_NASPortType.Wireless80211)); attributeList.add(new Attr_NASPort(new Long(1)));
To keep things simple, we only added the User-Name, NAS-Port-Type, and NAS-Port into the common attributes list. For authentication, however, we also must have the User-Password set (with the plain text password). We only need this attribute in the authentication packet, so we add it to the request directly before authenticating. For this example, we are authenticating using the MS-CHAPv2 protocol with 5 retries (should we not get a response).
RadiusPacket request = new AccessRequest(radiusClient, attributeList); request.addAttribute(new Attr_UserPassword("test")); System.out.println("Sending:\n" + request.toString()); RadiusPacket reply = radiusClient.authenticate(request, new MSCHAPv2Authenticator(), 5); if (reply == null) return; // Request Timed-out System.out.println("Received:\n" + reply.toString());
If our request times-out, reply will be null. Otherwise, reply will either be a AccessAccept or an AccessReject packet. We can test this and pull out the Reply-Message attribute value (if present) by doing the following:
Now, assuming we are authenticated, we can start sending accounting. But first, we add the Acct-Session-Id attribute to uniquely identify the session. For this we use a random string and we put it in the common attributes list. Since this is the start of accounting, we also add the Acct-Status-Type attribute set to Start.
attributeList.add(new Attr_AcctSessionId(RadiusRandom.getRandomString(24))); request = new AccountingRequest(radiusClient, attributeList); request.addAttribute(new Attr_AcctStatusType(Attr_AcctStatusType.Start)); reply = radiusClient.accounting(request, 5);
We send the accounting request packet with 5 retries. Again, if reply is null, then the request timed-out. Of course, you can now send additional Interim-Update accounting packets and ultimately a Stop packet.
request = new AccountingRequest(radiusClient, attributeList); request.addAttribute(new Attr_AcctStatusType(Attr_AcctStatusType.Stop)); request.addAttribute(new Attr_AcctInputOctets(new Long(10))); request.addAttribute(new Attr_AcctOutputOctets(new Long(10))); request.addAttribute(new Attr_AcctSessionTime(new Long(60))); request.addAttribute(new Attr_AcctTerminateCause(Attr_AcctTerminateCause.UserRequest)); reply = radiusClient.accounting(request, 5);
To conclude this example, we now send a stop packet with some bogus session data.