Both versions of Microsoft CHAP are handled both by the RADIUS client and server.
The RADIUS Server has a method in the AuthInfo class called cmpMSCHAP() that takes a password and examines the Microsoft Vendor-Specific attribute for CHAP challenge attributes. Both MS-CHAP and MS-CHAP V2 are handled by the same method. If the password matches the challenge the method returns true. Here's an example of detecting the challenge and comparing the result:
// If this is an MS-CHAP challenge then perform the necessary authentication.VendorSpecific msList[] = inList.getVendorSpecific(Microsoft.VENDORID); if (msList.length == 0) { auth.cmpMSCHAP(password.getBytes())) // Add response attributes and return auth.appendAttributes(responseList); return; }
The cmpMSCHAP() method will throw it's own AccessDropException if there are problems with the attributes and will throw an AccessRejectException with the proper MS CHAP error status if authentication fails.
The RADIUS client offers a way to create an MS-CHAP or MS-CHAP V2 challenge. The RADIUSClient.createCHAP() method creates the challenge attributes.
// MS-CHAP:
//
RADIUSClient rauth = new RADIUSClient(...);
// Create the attribute list and set some attributes.
AttributeList alist = new AttributeList();
alist.addAttribute(Attribute.NAS_Identifier, clientID);
alist.addAttribute(Attribute.NAS_Port, 1);
// Convert the name and password to UTF8 bytes.
byte nameBytes[] = rauth.getBytes("michael");
byte passwordBytes[] = rauth.getBytes("test");
// Add the User-Name attribute.
alist.addAttribute(Attribute.User_Name, nameBytes);
// Create the MSCHAP attributes in the current list.
rauth.createMSCHAP(passwordBytes, alist);
// Authenticate using only the attribute list.
rauth.authenticate(alist);
MS-CHAP V2 has a two step process - first the MS-CHAP V2 attributes are created and sent. Next the returned attributes are checked for correctness. This is a mutual authentication method where the server verifies the client and the client verifies the server.
// MS-CHAP V2:
//
RADIUSClient rauth = new RADIUSClient(...);
// Create the attribute list and set some attributes.
AttributeList alist = new AttributeList();
alist.addAttribute(Attribute.NAS_Identifier, clientID);
alist.addAttribute(Attribute.NAS_Port, 1);
// Convert the name and password to UTF8 bytes.
byte nameBytes[] = rauth.getBytes("michael");
byte passwordBytes[] = rauth.getBytes("test");
// Add the User-Name attribute.
alist.addAttribute(Attribute.User_Name, nameBytes);
// Create the MSCHAP 2 attributes in the current list.
rauth.createMSCHAP2(nameBytes, passwordBytes, alist);
// Authenticate using only the attribute list.
rauth.authenticate(alist);
// Get the returned attribute (assuming an Access-Accept)
AttributeList retList = rauth.getAttributes();
// Compare the MS-CHAP2 response:
if (rauth.cmpMSCHAP2(nameBytes, passwordBytes, retList) == true)
// All is well.
else
// The response was incorrect - something's wrong
// so reject the authentication.