⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 radiuspacket.java

📁 TinyRadius is a simple, small and fast Java Radius library capable of sending and receiving Radius
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
	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 + -