Each Radius UDR will be packed containing both the request and response UDRs for each case, along side the general NAS information, such as port and IP address.
Included with the Radius the Image Added Radius bundle is a general Radius format, containing all possible record types valid for Radius. The Radius agent will use this format for recognizing the type of data. The actual decoding of the contents (requestMessage), and the encoding of the reply (responseMessage) must be handled through a user defined format.
...
Info
title
Example - APL code to configure authentication using CHAP
Code Block
language
text
theme
Eclipse
import ultra.Default.rad_def;
initialize {
hashSetAlgorithm("MD5");
}
boolean isValidCHAP_Passwd(byte chap_iden,
bytearray chap_passwd,
bytearray password,
bytearray authenticator)
{
bytearray calc1 = baCreate(1);
baSet(calc1,0, chap_iden);
bytearray calc2 = baAppend(calc1, password);
bytearray calc3 = baAppend(calc2, authenticator);
hashReset();
hashUpdate(calc3);
bytearray res = hashDigest();
if (baSize(res) != baSize(chap_passwd)) {
return false;
}
int len = baSize(res);
int cnt = 0;
while (cnt < len) {
if (baGet(res,cnt) != baGet(chap_passwd, cnt))
{
return false;
}
cnt = cnt + 1;
}
// debug ("CHAP OK !!!!!!!!!!!!");
return true;
}
consume {
Radius r = (Radius)input;
string result;
list<drudr> UDRlist = listCreate(drudr);
if (r.requestMessage == null)
{
debug("Error???!!");
return;
}
result = udrDecode( "Request_Dec", // Decoder Name
UDRlist,
r.requestMessage,
true);
if (null != result)
{
debug("udrDecode FAILED: "+result);
return;
}
int i;
int antObjects = listSize(UDRlist);
drudr aReq;
while (i < antObjects)
{
aReq = listGet(UDRlist, i);
if (instanceOf(aReq, Accounting_Request_Int))
{
// debug("Accounting Request from: "+r.remoteIP+":"+r.remotePort);
Accounting_Request_Int req = (Accounting_Request_Int)aReq;
Accounting_Response_Int resp = udrCreate(Accounting_Response_Int);
resp.Code = 5;
resp.Identifier = req.Identifier;
resp.Authenticator = req.Authenticator;
resp.NAS_Port = req.Identifier;
r.responseMessage = udrEncode("Response_Enc", resp);
debug("Accounting Request: "+req.Identifier);
udrRoute(r, "Responses");
}
else if (instanceOf(aReq, Access_Request_Int))
{
boolean shouldReject = false;
string s_passwd = "hemligt"; // Lookup based on User-Name
bytearray b_passwd;
strToBA (b_passwd, s_passwd);
debug("Access Request from: "+r.remoteIP+":"+r.remotePort);
Access_Request_Int req = (Access_Request_Int)aReq;
Access_Accept_Int resp = udrCreate(Access_Accept_Int);
Access_Reject_Int rej = udrCreate(Access_Reject_Int);
rej.Code = 3;
rej.Identifier = req.Identifier;
rej.Authenticator = req.Authenticator;
resp.Code = 2;
resp.Identifier = req.Identifier;
resp.Authenticator = req.Authenticator;
resp.Login_TCP_Port = 6789; // Dummy for my tests ONLY
resp.NAS_Port = req.Identifier; // Dummy for my tests ONLY
if (udrIsPresent(req.CHAP_Password))
{
if (udrIsPresent(req.CHAP_Challenge)) {
// debug("CHAP Challenge based: "+req.CHAP_Challenge);
if (!isValidCHAP_Passwd(req.CHAP_Iden,req.CHAP_Password, b_passwd, req.CHAP_Challenge))
{
list<string> msg = listCreate(string, "CHAP failure: CHAP_Challenge based.");
shouldReject = true;
rej.Reply_Message = msg;
}
}
else {
string auth = baToStr(req.Authenticator);
// debug("Authenticator based: "+auth);
if (!isValidCHAP_Passwd(req.CHAP_Iden,req.CHAP_Password, b_passwd, req.Authenticator))
{
list<string> msg = listCreate(string, "CHAP failure: Authenticator based.");
shouldReject = true;
rej.Reply_Message = msg;
}
}
if (udrIsPresent(req.User_Password)) {
list<string> msg = listCreate(string, "Protocol ERROR: Both User_Password and CHAP_Password is present.");
shouldReject = true;
rej.Reply_Message = msg;
}
}
else if (udrIsPresent(req.User_Password))
{
// debug("User_Password: "+req.User_Password);
if ( (! strStartsWith(req.User_Password, s_passwd)) || (strLength(s_passwd) != strLength(req.User_Password))) {
list<string> msg = listCreate(string, "Invalid user name/password.");
shouldReject = true;
rej.Reply_Message = msg;
}
}
else
{
list<string> msg = listCreate(string, "STATE NOT SUPPORTED YET!");
shouldReject = true;
rej.Reply_Message = msg;
}
if (shouldReject)
{
r.responseMessage = udrEncode("Response_Enc", rej);
}
else
{
r.responseMessage = udrEncode("Response_Enc", resp);
}
debug(r.responseMessage);
udrRoute(r, "Responses");
}
else
{
debug("*** Invalid radius request from "+r.remoteIP+":"+r.remotePort+" ***");
}
i = i + 1;
}
}