📄 radiuspacket.java
字号:
public void setAuthenticator(byte[] authenticator) {
this.authenticator = authenticator;
}
/**
* Returns the dictionary this Radius packet uses.
* @return Dictionary instance
*/
public Dictionary getDictionary() {
return dictionary;
}
/**
* Sets a custom dictionary to use. If no dictionary is set,
* the default dictionary is used.
* Also copies the dictionary to the attributes.
* @param dictionary Dictionary class to use
* @see DefaultDictionary
*/
public void setDictionary(Dictionary dictionary) {
this.dictionary = dictionary;
for (Iterator i = attributes.iterator(); i.hasNext();) {
RadiusAttribute attr = (RadiusAttribute)i.next();
attr.setDictionary(dictionary);
}
}
/**
* Encodes this Radius packet and sends it to the specified output
* stream.
* @param out output stream to use
* @param sharedSecret shared secret to be used to encode this packet
* @param request Radius request packet if this packet to be encoded
* is a response packet, null if this packet is a request packet
* @exception IOException communication error
* @exception RuntimeException if required packet data has not been set
*/
protected void encodePacket(OutputStream out, String sharedSecret, RadiusPacket request)
throws IOException {
// check shared secret
if (sharedSecret == null || sharedSecret.length() == 0)
throw new RuntimeException("no shared secret has been set");
// check request authenticator
if (request != null && request.getAuthenticator() == null)
throw new RuntimeException("request authenticator not set");
// request packet authenticator
if (request == null) {
// first create authenticator, then encode attributes
// (User-Password attribute needs the authenticator)
authenticator = createRequestAuthenticator(sharedSecret);
encodeRequestAttributes(sharedSecret);
}
byte[] attributes = getAttributeBytes();
int packetLength = RADIUS_HEADER_LENGTH + attributes.length;
if (packetLength > MAX_PACKET_LENGTH)
throw new RuntimeException("packet too long");
// response packet authenticator
if (request != null) {
// after encoding attributes, create authenticator
authenticator = createResponseAuthenticator(sharedSecret, packetLength, attributes, request.getAuthenticator());
} else {
// update authenticator after encoding attributes
authenticator = updateRequestAuthenticator(sharedSecret, packetLength, attributes);
}
DataOutputStream dos = new DataOutputStream(out);
dos.writeByte(getPacketType());
dos.writeByte(getPacketIdentifier());
dos.writeShort(packetLength);
dos.write(getAuthenticator());
dos.write(attributes);
dos.flush();
}
/**
* This method exists for subclasses to be overridden in order to
* encode packet attributes like the User-Password attribute.
* The method may use getAuthenticator() to get the request
* authenticator.
* @param sharedSecret
*/
protected void encodeRequestAttributes(String sharedSecret) {
}
/**
* Creates a request authenticator for this packet. This request authenticator
* is constructed as described in RFC 2865.
* @param sharedSecret shared secret that secures the communication
* with the other Radius server/client
* @return request authenticator, 16 bytes
*/
protected byte[] createRequestAuthenticator(String sharedSecret) {
byte[] secretBytes = RadiusUtil.getUtf8Bytes(sharedSecret);
byte[] randomBytes = new byte[16];
random.nextBytes(randomBytes);
MessageDigest md5 = getMd5Digest();
md5.reset();
md5.update(secretBytes);
md5.update(randomBytes);
return md5.digest();
}
/**
* AccountingRequest overrides this
* method to create a request authenticator as specified by RFC 2866.
* @param sharedSecret shared secret
* @param packetLength length of the final Radius packet
* @param attributes attribute data
* @return new request authenticator
*/
protected byte[] updateRequestAuthenticator(String sharedSecret, int packetLength, byte[] attributes) {
return authenticator;
}
/**
* Creates an authenticator for a Radius response packet.
* @param sharedSecret shared secret
* @param packetLength length of response packet
* @param attributes encoded attributes of response packet
* @param requestAuthenticator request packet authenticator
* @return new 16 byte response authenticator
*/
protected byte[] createResponseAuthenticator(String sharedSecret, int packetLength, byte[] attributes, byte[] requestAuthenticator) {
MessageDigest md5 = getMd5Digest();
md5.reset();
md5.update((byte)getPacketType());
md5.update((byte)getPacketIdentifier());
md5.update((byte)(packetLength >> 8));
md5.update((byte)(packetLength & 0x0ff));
md5.update(requestAuthenticator, 0, requestAuthenticator.length);
md5.update(attributes, 0, attributes.length);
md5.update(RadiusUtil.getUtf8Bytes(sharedSecret));
return md5.digest();
}
/**
* Reads a Radius packet from the given input stream and
* creates an appropiate RadiusPacket descendant object.
* Reads in all attributes and returns the object.
* Decodes the encrypted fields and attributes of the packet.
* @param dictionary dictionary to use for attributes
* @param sharedSecret shared secret to be used to decode this packet
* @param request Radius request packet if this is a response packet to be
* decoded, null if this is a request packet to be decoded
* @return new RadiusPacket object
* @exception IOException if an IO error occurred
* @exception RadiusException if the Radius packet is malformed
*/
protected static RadiusPacket decodePacket(Dictionary dictionary, InputStream in, String sharedSecret, RadiusPacket request)
throws IOException, RadiusException {
// check shared secret
if (sharedSecret == null || sharedSecret.length() == 0)
throw new RuntimeException("no shared secret has been set");
// check request authenticator
if (request != null && request.getAuthenticator() == null)
throw new RuntimeException("request authenticator not set");
// read and check header
int type = in.read() & 0x0ff;
int identifier = in.read() & 0x0ff;
int length = (in.read() & 0x0ff) << 8 | (in.read() & 0x0ff);
if (request != null && request.getPacketIdentifier() != identifier)
throw new RadiusException("bad packet: invalid packet identifier (request: " + request.getPacketIdentifier() + ", response: " + identifier);
if (length < RADIUS_HEADER_LENGTH)
throw new RadiusException("bad packet: packet too short (" + length + " bytes)");
if (length > MAX_PACKET_LENGTH)
throw new RadiusException("bad packet: packet too long (" + length + " bytes)");
// read rest of packet
byte[] authenticator = new byte[16];
byte[] attributeData = new byte[length - RADIUS_HEADER_LENGTH];
in.read(authenticator);
in.read(attributeData);
// check and count attributes
int pos = 0;
int attributeCount = 0;
while (pos < attributeData.length) {
if (pos + 1 >= attributeData.length)
throw new RadiusException("bad packet: attribute length mismatch");
pos += attributeData[pos + 1] & 0x0ff;
attributeCount++;
}
if (pos != attributeData.length)
throw new RadiusException("bad packet: attribute length mismatch");
// create RadiusPacket object; set properties
RadiusPacket rp = createRadiusPacket(type);
rp.setPacketType(type);
rp.setPacketIdentifier(identifier);
rp.authenticator = authenticator;
// load attributes
pos = 0;
while (pos < attributeData.length) {
int attributeType = attributeData[pos] & 0x0ff;
int attributeLength = attributeData[pos + 1] & 0x0ff;
RadiusAttribute a = RadiusAttribute.createRadiusAttribute(dictionary, -1, attributeType);
a.readAttribute(attributeData, pos, attributeLength);
rp.addAttribute(a);
pos += attributeLength;
}
// request packet?
if (request == null) {
// decode attributes
rp.decodeRequestAttributes(sharedSecret);
rp.checkRequestAuthenticator(sharedSecret, length, attributeData);
} else {
// response packet: check authenticator
rp.checkResponseAuthenticator(sharedSecret, length, attributeData, request.getAuthenticator());
}
return rp;
}
/**
* Checks the request authenticator against the supplied shared secret.
* Overriden by AccountingRequest to handle special accounting request
* authenticators. There is no way to check request authenticators for
* authentication requests as they contain secret bytes.
* @param sharedSecret shared secret
* @param packetLength total length of the packet
* @param attributes request attribute data
*/
protected void checkRequestAuthenticator(String sharedSecret, int packetLength, byte[] attributes)
throws RadiusException {
}
/**
* Can be overriden to decode encoded request attributes such as
* User-Password. This method may use getAuthenticator() to get the
* request authenticator.
* @param sharedSecret
*/
protected void decodeRequestAttributes(String sharedSecret)
throws RadiusException {
}
/**
* This method checks the authenticator of this Radius packet. This method
* may be overriden to include special attributes in the authenticator check.
* @param sharedSecret shared secret to be used to encrypt the authenticator
* @param packetLength length of the response packet
* @param attributes attribute data of the response packet
* @param requestAuthenticator 16 bytes authenticator of the request packet belonging
* to this response packet
*/
protected void checkResponseAuthenticator(String sharedSecret, int packetLength, byte[] attributes, byte[] requestAuthenticator)
throws RadiusException {
byte[] authenticator = createResponseAuthenticator(sharedSecret, packetLength, attributes, requestAuthenticator);
byte[] receivedAuth = getAuthenticator();
for (int i = 0; i < 16; i++)
if (authenticator[i] != receivedAuth[i])
throw new RadiusException("response authenticator invalid");
}
/**
* Returns a MD5 digest.
* @return MessageDigest object
*/
protected MessageDigest getMd5Digest() {
if (md5Digest == null)
try {
md5Digest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException nsae) {
throw new RuntimeException("md5 digest not available", nsae);
}
return md5Digest;
}
/**
* Encodes the attributes of this Radius packet to a byte array.
* @return byte array with encoded attributes
* @throws IOException error writing data
*/
protected byte[] getAttributeBytes()
throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream(MAX_PACKET_LENGTH);
for (Iterator i = attributes.iterator(); i.hasNext();) {
RadiusAttribute a = (RadiusAttribute)i.next();
bos.write(a.writeAttribute());
}
bos.flush();
return bos.toByteArray();
}
/**
* Type of this Radius packet.
*/
private int packetType = 0;
/**
* Identifier of this packet.
*/
private int packetIdentifier = 0;
/**
* Attributes for this packet.
*/
private List attributes = new ArrayList();
/**
* MD5 digest.
*/
private MessageDigest md5Digest = null;
/**
* Authenticator for this Radius packet.
*/
private byte[] authenticator = null;
/**
* Dictionary to look up attribute names.
*/
private Dictionary dictionary = DefaultDictionary.getDefaultDictionary();
/**
* Next packet identifier.
*/
private static int nextPacketId = 0;
/**
* Random number generator.
*/
private static SecureRandom random = new SecureRandom();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -