Source code: RadiusMessageBuffer.java
|
[ index | 440 lines ]
|
package nl.west.aaa.radius;
import java.io.*;
import java.util.*;
class RadiusMessageBuffer
{
private static int DEFAULTBUFFERSIZE=1024;
private static int SPECIALVENDOR=
(('w'&0xff)<<24)|(('e'&0xff)<<16)|(('s'&0xff)<<8)|('t'&0xff);
private byte[] buffer;
private int idx;
/**
* Make a new empty RadiusMessagebuffer.
* No fields have been set and the buffer must be filled
* before sending.
*/
public RadiusMessageBuffer()
{
buffer=new byte[DEFAULTBUFFERSIZE];
idx=20;
buffer[2]=(byte)((idx>>8)&0xff);
buffer[3]=(byte)(idx&0xff);
}
/**
* Beging building a new buffer.
* authenticator.length=16
*/
public RadiusMessageBuffer(int code,int id,byte[] authenticator)
{
buffer=new byte[DEFAULTBUFFERSIZE];
buffer[0]=(byte)code;
buffer[1]=(byte)id;
System.arraycopy(authenticator,0,buffer,4,16);
idx=20;
buffer[2]=(byte)((idx>>8)&0xff);
buffer[3]=(byte)(idx&0xff);
}
/**
* Make a new MessageBuffer based on the data given.
*/
public RadiusMessageBuffer(byte[] data)
{
buffer=data;
idx=20;
}
public synchronized void setMessageCode(int code)
{
buffer[0]=(byte)code;
}
public synchronized void setMessageId(int id)
{
buffer[1]=(byte)id;
}
public synchronized void setMessageAuthenticator(byte[] authenticator)
{
System.arraycopy(authenticator,0,buffer,4,16);
}
public synchronized void addTextAVP(int type,String text)
{
try
{
addDataAVP(type,text.getBytes("UTF8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
public synchronized void addStringAVP(int type,String string)
{
try
{
addDataAVP(type,string.getBytes("ASCII"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
public synchronized void addAddressAVP(int type,String address)
{
StringTokenizer st=new StringTokenizer(address,".");
byte[] a=new byte[4];
a[0]=(byte)Integer.parseInt(st.nextToken());
a[1]=(byte)Integer.parseInt(st.nextToken());
a[2]=(byte)Integer.parseInt(st.nextToken());
a[3]=(byte)Integer.parseInt(st.nextToken());
addDataAVP(type,a);
}
public synchronized void addIntegerAVP(int type,int i)
{
byte[] n=new byte[4];
n[0]=(byte)((idx>>24)&0xff);
n[1]=(byte)((idx>>16)&0xff);
n[2]=(byte)((idx>>8)&0xff);
n[3]=(byte)(idx&0xff);
addDataAVP(type,n);
}
public synchronized void addDataAVP(int type,byte[] data)
{
if(buffer.length<idx+data.length+3)
{
byte[] tmp=new byte[(int)(2+buffer.length*1.8)];
System.arraycopy(buffer,0,tmp,0,buffer.length);
buffer=tmp;
}
buffer[idx++]=(byte)type;
buffer[idx++]=(byte)(data.length+2);
System.arraycopy(data,0,buffer,idx,data.length);
idx+=data.length;
// idx=length save msb first (save length)
buffer[2]=(byte)((idx>>8)&0xff);
buffer[3]=(byte)(idx&0xff);
}
public synchronized void addVendorAVP(int vendor,byte[] data)
{
byte[] tmp=new byte[data.length+4];
tmp[0]=(byte)((vendor>>24)&0xff);
tmp[1]=(byte)((vendor>>16)&0xff);
tmp[2]=(byte)((vendor>>8)&0xff);
tmp[3]=(byte)(vendor&0xff);
System.arraycopy(data,0,tmp,4,data.length);
addDataAVP(RadiusFormat.AVP_VENDOR_SPECIFIC,tmp);
}
/*
// NOT USED
public synchronized void addVendorAVP(int vendor,int vendorType,
int vendorLength,byte[] data)
{
byte[] tmp=new byte[data.length+2];
tmp[0]=(byte)vendorType;
tmp[1]=(byte)vendorLength;
System.arraycopy(data,0,tmp,2,data.length);
addVendorAVP(vendor,tmp);
}
*/
/**
* Dirty hack to send arbitrary attributes in RADIUS useing
* the vendor-specific attribute.
*/
public synchronized void addSpecialAVP(String name,String value)
{
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Length | Vendor-Id
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Vendor-Id (cont) | AVP name len | AVP name...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| AVP value...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
*/
try
{
byte[] nm=name.getBytes("UTF8");
byte[] vl=value.getBytes("UTF8");
byte[] tmp=new byte[nm.length+vl.length+1];
tmp[0]=(byte)nm.length;
System.arraycopy(nm,0,tmp,1,nm.length);
System.arraycopy(vl,0,tmp,1+nm.length,vl.length);
addVendorAVP(SPECIALVENDOR,tmp);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
/**
* Return the whole message as a byte array.
*/
public byte[] getBytes()
{
int len=getMessageLength();
byte[] res=new byte[len];
System.arraycopy(buffer,0,res,0,len);
return res;
}
/**
* Get the RADIUS code to identify the type
* of message.
*/
public int getMessageCode()
{
return buffer[0]&0xff;
}
/**
* Get the message-id.
*/
public int getMessageId()
{
return buffer[1]&0xff;
}
/**
* Get the length of the message.
*/
public int getMessageLength()
{
return ((buffer[2]&0xff)<<8)|(buffer[3]&0xff);
}
/**
* Get the message authenticator.
*/
public byte[] getMessageAuthenticator()
{
byte[] tmp=new byte[16];
System.arraycopy(buffer,4,tmp,0,16);
return tmp;
}
/**
* Reset the read-write position to the first
* AVP.
*/
public synchronized void setFirstAVP()
{
idx=20;
}
/**
* Check if more AVPs are available from this point.
*/
public boolean hasMoreAVPs()
{
return idx<getMessageLength();
}
/**
* Move the read-write pointer to the next AVP.
*/
public synchronized void nextAVP()
{
int len=buffer[idx+1]&0xff;
idx+=len;
}
/**
* Get the AVP Code.
*/
public synchronized int getAVPCode()
{
return buffer[idx]&0xff;
}
/**
* Get the AVP data, assuming it is text.
*/
public synchronized String getAVPText()
{
try
{
return new String(getAVPData(),"UTF8");
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
return null;
}
}
/**
* Get the AVP data, assuming it is a string.
*/
public synchronized String getAVPString()
{
try
{
return new String(getAVPData(),"ASCII");
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
return null;
}
}
/**
* Get the AVP data, assuming it is a address.
* Returns the string representation of the address.
* If the length of the data indicates that this cannot
* be an address, an Exception is thrown.
* <br>
* This method returns a string insteadof an InetAddress because
* InetAddress suggests that the host exists and this method
* could return 0.0.0.0 or 255.255.255.255 (which are valid
* values, but may not be valid real addresses).
*/
public synchronized String getAVPAddress()
{
byte[] tmp=getAVPData();
if(tmp.length!=4)
throw new RuntimeException("Attribute is not an address");
return (tmp[0]&0xff)+"."+
(tmp[1]&0xff)+"."+
(tmp[2]&0xff)+"."+
(tmp[3]&0xff);
}
/**
* Get the AVP data, assuming it is an integer.
* The result is an unsigned integer.
* If the length indicates the data cannot be an integer
* an exception is thrown.
*/
public synchronized int getAVPInteger()
{
byte[] tmp=getAVPData();
if(tmp.length!=4)
throw new RuntimeException("Attribute is not an integer");
int res=tmp[0]&0xff;
res=(res<<8)|tmp[1]&0xff;
res=(res<<8)|tmp[2]&0xff;
res=(res<<8)|tmp[3]&0xff;
return res;
}
/**
* Get the AVP data, assuming it is an integer.
* The results is a signed integer. (probably never used)
* If the length indicates the data cannot be an integer
* an exception is thrown.
*/
public synchronized int getAVPSignedInteger()
{
byte[] tmp=getAVPData();
if(tmp.length!=4)
throw new RuntimeException("Attribute is not an integer");
int res=tmp[0];
res=(res<<8)|tmp[1]&0xff;
res=(res<<8)|tmp[2]&0xff;
res=(res<<8)|tmp[3]&0xff;
return res;
}
/**
* Get the raw AVP data.
*/
public synchronized byte[] getAVPData()
{
int len=(buffer[idx+1]&0xff)-2;
byte[] tmp=new byte[len];
System.arraycopy(buffer,idx+2,tmp,0,len);
return tmp;
}
public synchronized int getAVPVendorID()
{
if(getAVPCode()!=RadiusFormat.AVP_VENDOR_SPECIFIC)
throw new RuntimeException("Attribute is not vendor specific");
byte[] tmp=getAVPData();
if(tmp.length<4)
throw new RuntimeException("Attribute is not valid vendor specific");
int res=tmp[0];
res=(res<<8)|tmp[1]&0xff;
res=(res<<8)|tmp[2]&0xff;
res=(res<<8)|tmp[3]&0xff;
return res;
}
public synchronized byte[] getAVPVendorData()
{
if(getAVPCode()!=RadiusFormat.AVP_VENDOR_SPECIFIC)
throw new RuntimeException("Attribute is not vendor specific");
byte[] tmp=getAVPData();
if(tmp.length<=4)
throw new RuntimeException("Attribute is not valid vendor specific");
byte[] res=new byte[tmp.length-4];
System.arraycopy(tmp,4,res,0,res.length);
return res;
}
public boolean isSpecialAVP()
{
if(getAVPCode()!=RadiusFormat.AVP_VENDOR_SPECIFIC)
return false;
if(getAVPData().length<7)
return false;
if(getAVPVendorID()!=SPECIALVENDOR)
return false;
return true;
}
public synchronized String getAVPSpecialName()
{
if(getAVPVendorID()!=SPECIALVENDOR)
throw new RuntimeException("Attribute is not special");
byte[] tmp=getAVPVendorData();
if(tmp.length<=4)
throw new RuntimeException("Attribute is not special");
int nlen=tmp[0]&0xff;
try
{
return new String(tmp,1,nlen,"UTF8");
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
return null;
}
}
public synchronized String getAVPSpecialValue()
{
if(getAVPVendorID()!=SPECIALVENDOR)
throw new RuntimeException("Attribute is not special");
byte[] tmp=getAVPVendorData();
if(tmp.length<=4)
throw new RuntimeException("Attribute is not special");
int nlen=tmp[0]&0xff;
try
{
return new String(tmp,1+nlen,tmp.length-1-nlen,"UTF8");
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
return null;
}
}
}
|