The Radius UDR(3.1)
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 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.
Field | Description |
---|---|
| If the |
| This field stores information about the context in which the operation has been invoked. |
| Provided that duplicate checking is enabled, and CRC32 is selected as method, this field will contain the calculated check sum for the packet. For all other cases it will be set to |
| This field indicates the type of Radius request, ACCESS_REQUEST, ACCOUNTING_REQUEST, DISCONNECT_REQUEST, or CHANGE_OF_AUTHORIZATION_REQUEST. |
| The IP address of the NAS. |
| The port used for communication with the NAS. |
| This field contains a request UDR. Depending on the settings on the NAS, it can be any of the following packet types: ACCESS_REQUEST In terms of authentication, CHAP is supported. PAP, MSCHAP and EAP are not fully supported. To use these protocols, you must configure the APL code as required. See the example below, APL code to configure authentication using CHAP. For details on these standards, see RFC 2865 (http://www.ietf.org/rfc/rfc2865.txt), RFC 2866 (http://www.ietf.org/rfc/rfc2866.txt) and RFC 5176 (http://www.ietf.org/rfc/rfc5176.txt). An Ultra Format Definition must be designed to handle decoding of this field. |
| The field containing a response UDR. Depending on the settings on the NAS, it can be any of the following packet types: ACCESS_ACCEPT In terms of authentication, CHAP is supported. PAP, MSCHAP and EAP are not fully supported. To use these protocols, you must configure the APL code as required. See the example below, APL code to configure authentication using CHAP. For details on these standards, see RFC 2865 (http://www.ietf.org/rfc/rfc2865.txt), RFC 2866 (http://www.ietf.org/rfc/rfc2866.txt) and RFC 5176 (http://www.ietf.org/rfc/rfc5176.txt). An Ultra Format Definition must be designed to handle decoding of this field. |
| The source IP address. |
| The source port. |
| The status message field is set to communicate status while a message is being sent or received. |
| This flag indicates whether the UDR has been throttled or not. Default is |
Example - APL code to configure authentication using CHAP
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; } }