This commit is contained in:
moznion
2020-12-07 23:28:38 +09:00
parent 93b951eff8
commit 3e6701b0b1
9 changed files with 79 additions and 13 deletions
+29
View File
@@ -34,6 +34,7 @@ pub type AVPType = u8;
pub const TYPE_INVALID: AVPType = 255;
/// This struct represents a attribute-value pair.
#[derive(Debug, Clone, PartialEq)]
pub struct AVP {
pub(crate) typ: AVPType,
@@ -41,6 +42,7 @@ pub struct AVP {
}
impl AVP {
/// (This method is for dictionary developers) make an AVP from a u32 value.
pub fn from_u32(typ: AVPType, value: u32) -> Self {
AVP {
typ,
@@ -48,6 +50,7 @@ impl AVP {
}
}
/// (This method is for dictionary developers) make an AVP from a u16 value.
pub fn from_u16(typ: AVPType, value: u16) -> Self {
AVP {
typ,
@@ -55,6 +58,7 @@ impl AVP {
}
}
/// (This method is for dictionary developers) make an AVP from a tagged u32 value.
pub fn from_tagged_u32(typ: AVPType, tag: Option<&Tag>, value: u32) -> Self {
let tag = match tag {
None => &Tag {
@@ -69,6 +73,7 @@ impl AVP {
}
}
/// (This method is for dictionary developers) make an AVP from a string value.
pub fn from_string(typ: AVPType, value: &str) -> Self {
AVP {
typ,
@@ -76,6 +81,7 @@ impl AVP {
}
}
/// (This method is for dictionary developers) make an AVP from a tagged string value.
pub fn from_tagged_string(typ: AVPType, tag: Option<&Tag>, value: &str) -> Self {
match tag {
None => AVP {
@@ -89,6 +95,7 @@ impl AVP {
}
}
/// (This method is for dictionary developers) make an AVP from bytes.
pub fn from_bytes(typ: AVPType, value: &[u8]) -> Self {
AVP {
typ,
@@ -96,6 +103,7 @@ impl AVP {
}
}
/// (This method is for dictionary developers) make an AVP from a IPv4 value.
pub fn from_ipv4(typ: AVPType, value: &Ipv4Addr) -> Self {
AVP {
typ,
@@ -103,6 +111,7 @@ impl AVP {
}
}
/// (This method is for dictionary developers) make an AVP from a IPv4-prefix value.
pub fn from_ipv4_prefix(typ: AVPType, prefix: &[u8]) -> Result<Self, AVPError> {
let prefix_len = prefix.len();
if prefix_len != 4 {
@@ -115,6 +124,7 @@ impl AVP {
})
}
/// (This method is for dictionary developers) make an AVP from a IPv6 value.
pub fn from_ipv6(typ: AVPType, value: &Ipv6Addr) -> Self {
AVP {
typ,
@@ -122,6 +132,7 @@ impl AVP {
}
}
/// (This method is for dictionary developers) make an AVP from a IPv6-prefix value.
pub fn from_ipv6_prefix(typ: AVPType, prefix: &[u8]) -> Result<Self, AVPError> {
let prefix_len = prefix.len();
if prefix_len > 16 {
@@ -134,6 +145,8 @@ impl AVP {
})
}
/// (This method is for dictionary developers) make an AVP from a user-password value.
/// see also: https://tools.ietf.org/html/rfc2865#section-5.2
pub fn from_user_password(
typ: AVPType,
plain_text: &[u8],
@@ -197,6 +210,7 @@ impl AVP {
Ok(AVP { typ, value: enc })
}
/// (This method is for dictionary developers) make an AVP from a date value.
pub fn from_date(typ: AVPType, dt: &DateTime<Utc>) -> Self {
AVP {
typ,
@@ -204,6 +218,8 @@ impl AVP {
}
}
/// (This method is for dictionary developers) make an AVP from a tunne-password value.
/// see also: https://tools.ietf.org/html/rfc2868#section-3.5
pub fn from_tunnel_password(
typ: AVPType,
tag: Option<&Tag>,
@@ -293,6 +309,7 @@ impl AVP {
Ok(AVP { typ, value: enc })
}
/// (This method is for dictionary developers) encode an AVP into a u32 value.
pub fn encode_u32(&self) -> Result<u32, AVPError> {
const U32_SIZE: usize = std::mem::size_of::<u32>();
if self.value.len() != U32_SIZE {
@@ -306,6 +323,7 @@ impl AVP {
}
}
/// (This method is for dictionary developers) encode an AVP into a u16 value.
pub fn encode_u16(&self) -> Result<u16, AVPError> {
const U16_SIZE: usize = std::mem::size_of::<u16>();
if self.value.len() != U16_SIZE {
@@ -319,6 +337,7 @@ impl AVP {
}
}
/// (This method is for dictionary developers) encode an AVP into a tag and u32 value.
pub fn encode_tagged_u32(&self) -> Result<(u32, Tag), AVPError> {
if self.value.is_empty() {
return Err(AVPError::InvalidAttributeLengthError(self.value.len()));
@@ -346,6 +365,7 @@ impl AVP {
}
}
/// (This method is for dictionary developers) encode an AVP into a string value.
pub fn encode_string(&self) -> Result<String, AVPError> {
match String::from_utf8(self.value.to_vec()) {
Ok(str) => Ok(str),
@@ -353,6 +373,7 @@ impl AVP {
}
}
/// (This method is for dictionary developers) encode an AVP into a tag and string value.
pub fn encode_tagged_string(&self) -> Result<(String, Option<Tag>), AVPError> {
let string_vec = self.value.to_vec();
if string_vec.is_empty() {
@@ -388,10 +409,12 @@ impl AVP {
}
}
/// (This method is for dictionary developers) encode an AVP into bytes.
pub fn encode_bytes(&self) -> Vec<u8> {
self.value.to_vec()
}
/// (This method is for dictionary developers) encode an AVP into Ipv4 value.
pub fn encode_ipv4(&self) -> Result<Ipv4Addr, AVPError> {
const IPV4_SIZE: usize = std::mem::size_of::<Ipv4Addr>();
if self.value.len() != IPV4_SIZE {
@@ -405,6 +428,7 @@ impl AVP {
}
}
/// (This method is for dictionary developers) encode an AVP into Ipv4-prefix value.
pub fn encode_ipv4_prefix(&self) -> Result<Vec<u8>, AVPError> {
match self.value.len() == 6 {
true => Ok(self.value[2..].to_owned()),
@@ -412,6 +436,7 @@ impl AVP {
}
}
/// (This method is for dictionary developers) encode an AVP into Ipv6 value.
pub fn encode_ipv6(&self) -> Result<Ipv6Addr, AVPError> {
const IPV6_SIZE: usize = std::mem::size_of::<Ipv6Addr>();
if self.value.len() != IPV6_SIZE {
@@ -425,6 +450,7 @@ impl AVP {
}
}
/// (This method is for dictionary developers) encode an AVP into Ipv6-prefix value.
pub fn encode_ipv6_prefix(&self) -> Result<Vec<u8>, AVPError> {
match self.value.len() >= 2 {
true => Ok(self.value[2..].to_owned()),
@@ -432,6 +458,7 @@ impl AVP {
}
}
/// (This method is for dictionary developers) encode an AVP into user-password value as bytes.
pub fn encode_user_password(
&self,
secret: &[u8],
@@ -475,6 +502,7 @@ impl AVP {
}
}
/// (This method is for dictionary developers) encode an AVP into date value.
pub fn encode_date(&self) -> Result<DateTime<Utc>, AVPError> {
const U32_SIZE: usize = std::mem::size_of::<u32>();
if self.value.len() != U32_SIZE {
@@ -491,6 +519,7 @@ impl AVP {
}
}
/// (This method is for dictionary developers) encode an AVP into a tunnel-password value as bytes.
pub fn encode_tunnel_password(
&self,
secret: &[u8],
+12
View File
@@ -26,6 +26,7 @@ pub enum PacketError {
UnknownCodeError(String),
}
/// This struct represents a packet of RADIUS for request and response.
#[derive(Debug, Clone, PartialEq)]
pub struct Packet {
code: Code,
@@ -36,6 +37,7 @@ pub struct Packet {
}
impl Packet {
/// Constructor for a Packet.
pub fn new(code: Code, secret: &[u8]) -> Self {
let mut rng = rand::thread_rng();
let authenticator = (0..16).map(|_| rng.gen()).collect::<Vec<u8>>();
@@ -64,6 +66,7 @@ impl Packet {
&self.authenticator
}
/// This decodes bytes into a Packet.
pub fn decode(bs: &[u8], secret: &[u8]) -> Result<Self, PacketError> {
if bs.len() < RADIUS_PACKET_HEADER_LENGTH {
return Err(PacketError::InsufficientPacketLengthError(
@@ -93,6 +96,7 @@ impl Packet {
})
}
/// This method makes a response packet according to self (i.e. request packet).
pub fn make_response_packet(&self, code: Code) -> Self {
Packet {
code,
@@ -103,6 +107,7 @@ impl Packet {
}
}
/// This method encodes the Packet into bytes.
pub fn encode(&self) -> Result<Vec<u8>, PacketError> {
let mut bs = match self.marshal_binary() {
Ok(bs) => bs,
@@ -181,6 +186,7 @@ impl Packet {
Ok(bs)
}
/// Returns whether the Packet is authentic response or not.
pub fn is_authentic_response(response: &[u8], request: &[u8], secret: &[u8]) -> bool {
if response.len() < RADIUS_PACKET_HEADER_LENGTH
|| request.len() < RADIUS_PACKET_HEADER_LENGTH
@@ -202,6 +208,7 @@ impl Packet {
.eq(&response[4..RADIUS_PACKET_HEADER_LENGTH].to_vec())
}
/// Returns whether the Packet is authentic request or not.
pub fn is_authentic_request(request: &[u8], secret: &[u8]) -> bool {
if request.len() < RADIUS_PACKET_HEADER_LENGTH || secret.is_empty() {
return false;
@@ -227,22 +234,27 @@ impl Packet {
}
}
/// Add an AVP to the list of AVPs.
pub fn add(&mut self, avp: AVP) {
self.attributes.add(avp);
}
/// Add AVPs to the list of AVPs.
pub fn extend(&mut self, avps: Vec<AVP>) {
self.attributes.extend(avps)
}
/// Delete all of AVPs from the list according to given AVP type.
pub fn delete(&mut self, typ: AVPType) {
self.attributes.del(typ);
}
/// Returns an AVP that matches at first with the given AVP type. If there are not any matched ones, this returns `None`.
pub fn lookup(&self, typ: AVPType) -> Option<&AVP> {
self.attributes.lookup(typ)
}
/// Returns AVPs that match with the given AVP type.
pub fn lookup_all(&self, typ: AVPType) -> Vec<&AVP> {
self.attributes.lookup_all(typ)
}
+1
View File
@@ -2,6 +2,7 @@ use std::net::SocketAddr;
use crate::packet::Packet;
/// RADIUS request object.
pub struct Request {
local_addr: SocketAddr,
remote_addr: SocketAddr,
+2
View File
@@ -1,5 +1,7 @@
pub(crate) const UNUSED_TAG_VALUE: u8 = 0x00;
/// Tag represents a tag of a RADIUS value.
/// see also: http://www.ietf.org/rfc/rfc2868.html
#[derive(Debug, PartialEq)]
pub struct Tag {
pub(crate) value: u8,