/**
* JRadius - A RADIUS Server Java Adapter
* Copyright (C) 2004-2006 PicoPoint, B.V.
* Copyright (C) 2006-2007 David Bird <david@coova.com>
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package net.jradius.packet;
import java.io.Serializable;
import net.jradius.exception.UnknownAttributeException;
import net.jradius.packet.attribute.AttributeList;
import net.jradius.packet.attribute.RadiusAttribute;
import net.jradius.packet.attribute.value.AttributeValue;
/**
* Represents a Radius Packet. All radius packet classes are derived
* from this abstract class.
*
* @author David Bird
*/
public abstract class RadiusPacket implements Serializable
{
private static final long serialVersionUID = 0L;
public static final int MIN_PACKET_LENGTH = 20;
public static final int MAX_PACKET_LENGTH = 4096;
public static final short RADIUS_HEADER_LENGTH = 20;
private static Object nextPacketIdLock = new Object();
private static int nextPacketId = 1;
protected int code;
protected int identifier = -1;
protected byte[] authenticator;
protected final AttributeList attributes = new AttributeList();
protected boolean recyclable;
protected boolean recycled;
/**
* Default Constructor
*/
public RadiusPacket()
{
}
/**
* Constructs a RadiusPacket with an AttributeList
* @param list Initial AttributeList
*/
public RadiusPacket(AttributeList list)
{
if (list != null)
{
attributes.copy(list, recyclable);
}
}
/**
* @param code The code to set
*/
public void setCode(int code)
{
this.code = (byte)code;
}
/**
* @return Returns the code of the RadiusPacket
*/
public int getCode()
{
return code;
}
/**
* Adds an attribute to a RadiusPacket (without overriding any
* existing attributes)
* @param attribute The attribute to add
*/
public void addAttribute(RadiusAttribute attribute)
{
if (null != attribute)
{
attributes.add(attribute, false);
}
}
/**
* Adds an attribute to a RadiusPacket overwriting any existing attribute
* @param attribute The attribute to add
*/
public void overwriteAttribute(RadiusAttribute attribute)
{
if (null != attribute)
{
attributes.add(attribute, true);
}
}
/**
* Adds the contents of an AttributeList to a RadiusPacket
* @param list The attributes to add
*/
public void addAttributes(AttributeList list)
{
attributes.add(list);
}
/**
* Removes an attribute
* @param attribute The RadiusAttribute to be removed
*/
public void removeAttribute(RadiusAttribute attribute)
{
attributes.remove(attribute);
}
/**
* Removes an attribute
* @param attributeType The attribute type to be removed
*/
public void removeAttribute(long attributeType)
{
attributes.remove(attributeType);
}
/**
* Get the Identifier of the RadiusPacket (creating one if needed)
* @return Returns the RadiusPacket Identifier
*/
public int getIdentifier()
{
if (this.identifier < 0)
{
this.identifier = getNewPacketId();
}
return this.identifier;
}
/**
* Set the Identifier byte of a RadiusPacket
* @param i The new Identifier
*/
public void setIdentifier(int i)
{
this.identifier = i;
}
/**
* Get the attributes of a RadiusPacket
* @return Returns the AttributeList of the packet
*/
public AttributeList getAttributes()
{
return attributes;
}
/**
* Derived RadiusRequest classes must override this
* @param attributes
* @return Returns 16 bytes
*/
public byte[] createAuthenticator(byte[] attributes, int offset, int attributsLength, String sharedSecret)
{
return new byte[16];
}
public boolean verifyAuthenticator(String sharedSecret)
{
return false;
}
/**
* @param authenticator The authenticator to set.
*/
public void setAuthenticator(byte[] authenticator)
{
this.authenticator = authenticator;
}
/**
* @return Returns the packet authenticator
*/
public byte[] getAuthenticator()
{
return this.authenticator;
}
/**
* Get (or generate) the RADIUS Authenticator
* @param attributes
* @return Returns the packet authenticator
*/
public byte[] getAuthenticator(byte[] attributes, String sharedSecret)
{
if (this.authenticator == null)
{
if (sharedSecret != null)
this.authenticator = createAuthenticator(attributes, 0, attributes.length, sharedSecret);
else
this.authenticator = new byte[16];
}
return this.authenticator;
}
public byte[] getAuthenticator(byte[] attributes, int offset, int attributesLength, String sharedSecret)
{
if (this.authenticator == null)
{
if (sharedSecret != null)
this.authenticator = createAuthenticator(attributes, offset, attributesLength, sharedSecret);
else
this.authenticator = new byte[16];
}
return this.authenticator;
}
/**
* @param type The attribute type
* @return Returns the attribute, if found
*/
public RadiusAttribute findAttribute(long type)
{
return attributes.get(type);
}
/**
* @param type The integer type of the attribute to find
* @return Returns an array of RadiusAttributes
*/
public Object[] findAttributes(long type)
{
return attributes.getArray(type);
}
/**
* @param aName The name of the attribute to find
* @return Returns the RadiusAttribute, null if not found
* @throws UnknownAttributeException
*/
public RadiusAttribute findAttribute(String aName) throws UnknownAttributeException
{
return attributes.get(aName);
}
/**
* @param type The integer type of the attribute to find
* @return Returns the Object value of the found attribute, otherwise null
*/
public Object getAttributeValue(long type)
{
return attributes.getValue(type);
}
/**
* @param aName The name of the attribute to find
* @return Returns the Object value of the found attribute, otherwise null
* @throws UnknownAttributeException
*/
public Object getAttributeValue(String aName)
throws UnknownAttributeException
{
RadiusAttribute attribute = findAttribute(aName);
if (attribute != null)
{
AttributeValue value = attribute.getValue();
if (value != null)
{
return value.getValueObject();
}
}
return null;
}
/**
* @return Returns the next RadiusPacket Identifier to be used
*/
private static int getNewPacketId()
{
synchronized (nextPacketIdLock)
{
nextPacketId = (nextPacketId + 1) % 255;
return nextPacketId;
}
}
/**
* Formats the RadiusPacket into a String
*/
public String toString(boolean nonStandardAtts, boolean unknownAttrs)
{
StringBuffer sb = new StringBuffer();
sb.append("Class: ").append(this.getClass().toString()).append("\n");
sb.append("Attributes:\n");
sb.append(attributes.toString(nonStandardAtts, unknownAttrs));
return sb.toString();
}
public String toString()
{
return toString(true, true);
}
public boolean isRecyclable() {
return recyclable;
}
}