Support RFC2869

This commit is contained in:
moznion
2020-12-03 02:21:33 +09:00
parent 7c0ca5bb9b
commit 84f225b4c0
7 changed files with 427 additions and 2 deletions
+1 -1
View File
@@ -14,6 +14,7 @@ This supports the following RFC dictionaries at the moment:
- [RFC2866](https://tools.ietf.org/html/rfc2866) - [RFC2866](https://tools.ietf.org/html/rfc2866)
- [RFC2867](https://tools.ietf.org/html/rfc2867) - [RFC2867](https://tools.ietf.org/html/rfc2867)
- [RFC2868](https://tools.ietf.org/html/rfc2868) - [RFC2868](https://tools.ietf.org/html/rfc2868)
- [RFC2869](https://tools.ietf.org/html/rfc2869)
- [RFC3576](https://tools.ietf.org/html/rfc3576) - [RFC3576](https://tools.ietf.org/html/rfc3576)
- [RFC4072](https://tools.ietf.org/html/rfc4072) - [RFC4072](https://tools.ietf.org/html/rfc4072)
- [RFC5090](https://tools.ietf.org/html/rfc5090) - [RFC5090](https://tools.ietf.org/html/rfc5090)
@@ -32,7 +33,6 @@ Simple example implementations are here:
- retransmission feature on the client - retransmission feature on the client
- Support the following RFC dictionaries: - Support the following RFC dictionaries:
- rfc2869
- rfc3162 - rfc3162
- rfc3580 - rfc3580
- rfc4372 - rfc4372
+42
View File
@@ -0,0 +1,42 @@
# -*- text -*-
# Copyright (C) 2020 The FreeRADIUS Server project and contributors
# This work is licensed under CC-BY version 4.0 https://creativecommons.org/licenses/by/4.0
# Version $Id$
#
# Attributes and values defined in RFC 2869.
# http://www.ietf.org/rfc/rfc2869.txt
#
# $Id$
#
ATTRIBUTE Acct-Input-Gigawords 52 integer
ATTRIBUTE Acct-Output-Gigawords 53 integer
ATTRIBUTE Event-Timestamp 55 date
ATTRIBUTE ARAP-Password 70 octets[16]
ATTRIBUTE ARAP-Features 71 octets[14]
ATTRIBUTE ARAP-Zone-Access 72 integer
ATTRIBUTE ARAP-Security 73 integer
ATTRIBUTE ARAP-Security-Data 74 string
ATTRIBUTE Password-Retry 75 integer
ATTRIBUTE Prompt 76 integer
ATTRIBUTE Connect-Info 77 string
ATTRIBUTE Configuration-Token 78 string
ATTRIBUTE EAP-Message 79 octets concat
ATTRIBUTE Message-Authenticator 80 octets
ATTRIBUTE ARAP-Challenge-Response 84 octets[8]
ATTRIBUTE Acct-Interim-Interval 85 integer
# 86: RFC 2867
ATTRIBUTE NAS-Port-Id 87 string
ATTRIBUTE Framed-Pool 88 string
# ARAP Zone Access
VALUE ARAP-Zone-Access Default-Zone 1
VALUE ARAP-Zone-Access Zone-Filter-Inclusive 2
VALUE ARAP-Zone-Access Zone-Filter-Exclusive 4
# Prompt
VALUE Prompt No-Echo 0
VALUE Prompt Echo 1
+4
View File
@@ -37,6 +37,10 @@ impl Attributes {
self.0.push(avp) self.0.push(avp)
} }
pub(crate) fn extend(&mut self, avps: Vec<AVP>) {
self.0.extend(avps)
}
pub(crate) fn del(&mut self, typ: AVPType) { pub(crate) fn del(&mut self, typ: AVPType) {
self.0 = self self.0 = self
.0 .0
+1 -1
View File
@@ -19,7 +19,7 @@ pub enum AVPError {
InvalidRequestAuthenticatorLength(), InvalidRequestAuthenticatorLength(),
#[error("invalid attribute length: {0}")] #[error("invalid attribute length: {0}")]
InvalidAttributeLengthError(usize), InvalidAttributeLengthError(usize),
// TODO: more meaningful error message // ^ TODO: more meaningful error message
#[error("unexpected decoding error: {0}")] #[error("unexpected decoding error: {0}")]
UnexpectedDecodingError(String), UnexpectedDecodingError(String),
#[error("invalid salt. the MSB has to be 1, but given value isn't: {0}")] #[error("invalid salt. the MSB has to be 1, but given value isn't: {0}")]
+1
View File
@@ -7,6 +7,7 @@ pub mod rfc2865;
pub mod rfc2866; pub mod rfc2866;
pub mod rfc2867; pub mod rfc2867;
pub mod rfc2868; pub mod rfc2868;
pub mod rfc2869;
pub mod rfc3576; pub mod rfc3576;
pub mod rfc4072; pub mod rfc4072;
pub mod rfc5090; pub mod rfc5090;
+4
View File
@@ -231,6 +231,10 @@ impl Packet {
self.attributes.add(avp); self.attributes.add(avp);
} }
pub fn extend(&mut self, avps: Vec<AVP>) {
self.attributes.extend(avps)
}
pub fn delete(&mut self, typ: AVPType) { pub fn delete(&mut self, typ: AVPType) {
self.attributes.del(typ); self.attributes.del(typ);
} }
+374
View File
@@ -0,0 +1,374 @@
// Code generated by machine generator; DO NOT EDIT.
use chrono::{DateTime, Utc};
use crate::avp::{AVPError, AVPType, AVP};
use crate::packet::Packet;
pub type ArapZoneAccess = u32;
pub const ARAP_ZONE_ACCESS_DEFAULT_ZONE: ArapZoneAccess = 1;
pub const ARAP_ZONE_ACCESS_ZONE_FILTER_INCLUSIVE: ArapZoneAccess = 2;
pub const ARAP_ZONE_ACCESS_ZONE_FILTER_EXCLUSIVE: ArapZoneAccess = 4;
pub type Prompt = u32;
pub const PROMPT_NO_ECHO: Prompt = 0;
pub const PROMPT_ECHO: Prompt = 1;
pub const ACCT_INPUT_GIGAWORDS_TYPE: AVPType = 52;
pub fn delete_acct_input_gigawords(packet: &mut Packet) {
packet.delete(ACCT_INPUT_GIGAWORDS_TYPE);
}
pub fn add_acct_input_gigawords(packet: &mut Packet, value: u32) {
packet.add(AVP::from_u32(ACCT_INPUT_GIGAWORDS_TYPE, value));
}
pub fn lookup_acct_input_gigawords(packet: &Packet) -> Option<Result<u32, AVPError>> {
packet
.lookup(ACCT_INPUT_GIGAWORDS_TYPE)
.map(|v| v.encode_u32())
}
pub fn lookup_all_acct_input_gigawords(packet: &Packet) -> Result<Vec<u32>, AVPError> {
let mut vec = Vec::new();
for avp in packet.lookup_all(ACCT_INPUT_GIGAWORDS_TYPE) {
vec.push(avp.encode_u32()?)
}
Ok(vec)
}
pub const ACCT_OUTPUT_GIGAWORDS_TYPE: AVPType = 53;
pub fn delete_acct_output_gigawords(packet: &mut Packet) {
packet.delete(ACCT_OUTPUT_GIGAWORDS_TYPE);
}
pub fn add_acct_output_gigawords(packet: &mut Packet, value: u32) {
packet.add(AVP::from_u32(ACCT_OUTPUT_GIGAWORDS_TYPE, value));
}
pub fn lookup_acct_output_gigawords(packet: &Packet) -> Option<Result<u32, AVPError>> {
packet
.lookup(ACCT_OUTPUT_GIGAWORDS_TYPE)
.map(|v| v.encode_u32())
}
pub fn lookup_all_acct_output_gigawords(packet: &Packet) -> Result<Vec<u32>, AVPError> {
let mut vec = Vec::new();
for avp in packet.lookup_all(ACCT_OUTPUT_GIGAWORDS_TYPE) {
vec.push(avp.encode_u32()?)
}
Ok(vec)
}
pub const EVENT_TIMESTAMP_TYPE: AVPType = 55;
pub fn delete_event_timestamp(packet: &mut Packet) {
packet.delete(EVENT_TIMESTAMP_TYPE);
}
pub fn add_event_timestamp(packet: &mut Packet, value: &DateTime<Utc>) {
packet.add(AVP::from_date(EVENT_TIMESTAMP_TYPE, value));
}
pub fn lookup_event_timestamp(packet: &Packet) -> Option<Result<DateTime<Utc>, AVPError>> {
packet.lookup(EVENT_TIMESTAMP_TYPE).map(|v| v.encode_date())
}
pub fn lookup_all_event_timestamp(packet: &Packet) -> Result<Vec<DateTime<Utc>>, AVPError> {
let mut vec = Vec::new();
for avp in packet.lookup_all(EVENT_TIMESTAMP_TYPE) {
vec.push(avp.encode_date()?)
}
Ok(vec)
}
pub const ARAP_PASSWORD_TYPE: AVPType = 70;
pub fn delete_arap_password(packet: &mut Packet) {
packet.delete(ARAP_PASSWORD_TYPE);
}
pub fn add_arap_password(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> {
if value.len() != 16 {
return Err(AVPError::InvalidAttributeLengthError(16));
}
packet.add(AVP::from_bytes(ARAP_PASSWORD_TYPE, value));
Ok(())
}
pub fn lookup_arap_password(packet: &Packet) -> Option<Vec<u8>> {
packet.lookup(ARAP_PASSWORD_TYPE).map(|v| v.encode_bytes())
}
pub fn lookup_all_arap_password(packet: &Packet) -> Vec<Vec<u8>> {
let mut vec = Vec::new();
for avp in packet.lookup_all(ARAP_PASSWORD_TYPE) {
vec.push(avp.encode_bytes())
}
vec
}
pub const ARAP_FEATURES_TYPE: AVPType = 71;
pub fn delete_arap_features(packet: &mut Packet) {
packet.delete(ARAP_FEATURES_TYPE);
}
pub fn add_arap_features(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> {
if value.len() != 14 {
return Err(AVPError::InvalidAttributeLengthError(14));
}
packet.add(AVP::from_bytes(ARAP_FEATURES_TYPE, value));
Ok(())
}
pub fn lookup_arap_features(packet: &Packet) -> Option<Vec<u8>> {
packet.lookup(ARAP_FEATURES_TYPE).map(|v| v.encode_bytes())
}
pub fn lookup_all_arap_features(packet: &Packet) -> Vec<Vec<u8>> {
let mut vec = Vec::new();
for avp in packet.lookup_all(ARAP_FEATURES_TYPE) {
vec.push(avp.encode_bytes())
}
vec
}
pub const ARAP_ZONE_ACCESS_TYPE: AVPType = 72;
pub fn delete_arap_zone_access(packet: &mut Packet) {
packet.delete(ARAP_ZONE_ACCESS_TYPE);
}
pub fn add_arap_zone_access(packet: &mut Packet, value: ArapZoneAccess) {
packet.add(AVP::from_u32(ARAP_ZONE_ACCESS_TYPE, value as u32));
}
pub fn lookup_arap_zone_access(packet: &Packet) -> Option<Result<ArapZoneAccess, AVPError>> {
packet
.lookup(ARAP_ZONE_ACCESS_TYPE)
.map(|v| Ok(v.encode_u32()? as ArapZoneAccess))
}
pub fn lookup_all_arap_zone_access(packet: &Packet) -> Result<Vec<ArapZoneAccess>, AVPError> {
let mut vec = Vec::new();
for avp in packet.lookup_all(ARAP_ZONE_ACCESS_TYPE) {
vec.push(avp.encode_u32()? as ArapZoneAccess)
}
Ok(vec)
}
pub const ARAP_SECURITY_TYPE: AVPType = 73;
pub fn delete_arap_security(packet: &mut Packet) {
packet.delete(ARAP_SECURITY_TYPE);
}
pub fn add_arap_security(packet: &mut Packet, value: u32) {
packet.add(AVP::from_u32(ARAP_SECURITY_TYPE, value));
}
pub fn lookup_arap_security(packet: &Packet) -> Option<Result<u32, AVPError>> {
packet.lookup(ARAP_SECURITY_TYPE).map(|v| v.encode_u32())
}
pub fn lookup_all_arap_security(packet: &Packet) -> Result<Vec<u32>, AVPError> {
let mut vec = Vec::new();
for avp in packet.lookup_all(ARAP_SECURITY_TYPE) {
vec.push(avp.encode_u32()?)
}
Ok(vec)
}
pub const ARAP_SECURITY_DATA_TYPE: AVPType = 74;
pub fn delete_arap_security_data(packet: &mut Packet) {
packet.delete(ARAP_SECURITY_DATA_TYPE);
}
pub fn add_arap_security_data(packet: &mut Packet, value: &str) {
packet.add(AVP::from_string(ARAP_SECURITY_DATA_TYPE, value));
}
pub fn lookup_arap_security_data(packet: &Packet) -> Option<Result<String, AVPError>> {
packet
.lookup(ARAP_SECURITY_DATA_TYPE)
.map(|v| v.encode_string())
}
pub fn lookup_all_arap_security_data(packet: &Packet) -> Result<Vec<String>, AVPError> {
let mut vec = Vec::new();
for avp in packet.lookup_all(ARAP_SECURITY_DATA_TYPE) {
vec.push(avp.encode_string()?)
}
Ok(vec)
}
pub const PASSWORD_RETRY_TYPE: AVPType = 75;
pub fn delete_password_retry(packet: &mut Packet) {
packet.delete(PASSWORD_RETRY_TYPE);
}
pub fn add_password_retry(packet: &mut Packet, value: u32) {
packet.add(AVP::from_u32(PASSWORD_RETRY_TYPE, value));
}
pub fn lookup_password_retry(packet: &Packet) -> Option<Result<u32, AVPError>> {
packet.lookup(PASSWORD_RETRY_TYPE).map(|v| v.encode_u32())
}
pub fn lookup_all_password_retry(packet: &Packet) -> Result<Vec<u32>, AVPError> {
let mut vec = Vec::new();
for avp in packet.lookup_all(PASSWORD_RETRY_TYPE) {
vec.push(avp.encode_u32()?)
}
Ok(vec)
}
pub const PROMPT_TYPE: AVPType = 76;
pub fn delete_prompt(packet: &mut Packet) {
packet.delete(PROMPT_TYPE);
}
pub fn add_prompt(packet: &mut Packet, value: Prompt) {
packet.add(AVP::from_u32(PROMPT_TYPE, value as u32));
}
pub fn lookup_prompt(packet: &Packet) -> Option<Result<Prompt, AVPError>> {
packet
.lookup(PROMPT_TYPE)
.map(|v| Ok(v.encode_u32()? as Prompt))
}
pub fn lookup_all_prompt(packet: &Packet) -> Result<Vec<Prompt>, AVPError> {
let mut vec = Vec::new();
for avp in packet.lookup_all(PROMPT_TYPE) {
vec.push(avp.encode_u32()? as Prompt)
}
Ok(vec)
}
pub const CONNECT_INFO_TYPE: AVPType = 77;
pub fn delete_connect_info(packet: &mut Packet) {
packet.delete(CONNECT_INFO_TYPE);
}
pub fn add_connect_info(packet: &mut Packet, value: &str) {
packet.add(AVP::from_string(CONNECT_INFO_TYPE, value));
}
pub fn lookup_connect_info(packet: &Packet) -> Option<Result<String, AVPError>> {
packet.lookup(CONNECT_INFO_TYPE).map(|v| v.encode_string())
}
pub fn lookup_all_connect_info(packet: &Packet) -> Result<Vec<String>, AVPError> {
let mut vec = Vec::new();
for avp in packet.lookup_all(CONNECT_INFO_TYPE) {
vec.push(avp.encode_string()?)
}
Ok(vec)
}
pub const CONFIGURATION_TOKEN_TYPE: AVPType = 78;
pub fn delete_configuration_token(packet: &mut Packet) {
packet.delete(CONFIGURATION_TOKEN_TYPE);
}
pub fn add_configuration_token(packet: &mut Packet, value: &str) {
packet.add(AVP::from_string(CONFIGURATION_TOKEN_TYPE, value));
}
pub fn lookup_configuration_token(packet: &Packet) -> Option<Result<String, AVPError>> {
packet
.lookup(CONFIGURATION_TOKEN_TYPE)
.map(|v| v.encode_string())
}
pub fn lookup_all_configuration_token(packet: &Packet) -> Result<Vec<String>, AVPError> {
let mut vec = Vec::new();
for avp in packet.lookup_all(CONFIGURATION_TOKEN_TYPE) {
vec.push(avp.encode_string()?)
}
Ok(vec)
}
pub const EAP_MESSAGE_TYPE: AVPType = 79;
pub fn delete_eap_message(packet: &mut Packet) {
packet.delete(EAP_MESSAGE_TYPE);
}
pub fn add_eap_message(packet: &mut Packet, value: &[u8]) {
packet.extend(
value
.chunks(253)
.map(|chunk| AVP::from_bytes(EAP_MESSAGE_TYPE, chunk))
.collect(),
);
}
pub fn lookup_eap_message(packet: &Packet) -> Option<Vec<u8>> {
let avps = packet.lookup_all(EAP_MESSAGE_TYPE);
match avps.is_empty() {
true => None,
false => Some(avps.into_iter().fold(Vec::new(), |mut acc, v| {
acc.extend(v.encode_bytes());
acc
})),
}
}
pub const MESSAGE_AUTHENTICATOR_TYPE: AVPType = 80;
pub fn delete_message_authenticator(packet: &mut Packet) {
packet.delete(MESSAGE_AUTHENTICATOR_TYPE);
}
pub fn add_message_authenticator(packet: &mut Packet, value: &[u8]) {
packet.add(AVP::from_bytes(MESSAGE_AUTHENTICATOR_TYPE, value));
}
pub fn lookup_message_authenticator(packet: &Packet) -> Option<Vec<u8>> {
packet
.lookup(MESSAGE_AUTHENTICATOR_TYPE)
.map(|v| v.encode_bytes())
}
pub fn lookup_all_message_authenticator(packet: &Packet) -> Vec<Vec<u8>> {
let mut vec = Vec::new();
for avp in packet.lookup_all(MESSAGE_AUTHENTICATOR_TYPE) {
vec.push(avp.encode_bytes())
}
vec
}
pub const ARAP_CHALLENGE_RESPONSE_TYPE: AVPType = 84;
pub fn delete_arap_challenge_response(packet: &mut Packet) {
packet.delete(ARAP_CHALLENGE_RESPONSE_TYPE);
}
pub fn add_arap_challenge_response(packet: &mut Packet, value: &[u8]) -> Result<(), AVPError> {
if value.len() != 8 {
return Err(AVPError::InvalidAttributeLengthError(8));
}
packet.add(AVP::from_bytes(ARAP_CHALLENGE_RESPONSE_TYPE, value));
Ok(())
}
pub fn lookup_arap_challenge_response(packet: &Packet) -> Option<Vec<u8>> {
packet
.lookup(ARAP_CHALLENGE_RESPONSE_TYPE)
.map(|v| v.encode_bytes())
}
pub fn lookup_all_arap_challenge_response(packet: &Packet) -> Vec<Vec<u8>> {
let mut vec = Vec::new();
for avp in packet.lookup_all(ARAP_CHALLENGE_RESPONSE_TYPE) {
vec.push(avp.encode_bytes())
}
vec
}
pub const ACCT_INTERIM_INTERVAL_TYPE: AVPType = 85;
pub fn delete_acct_interim_interval(packet: &mut Packet) {
packet.delete(ACCT_INTERIM_INTERVAL_TYPE);
}
pub fn add_acct_interim_interval(packet: &mut Packet, value: u32) {
packet.add(AVP::from_u32(ACCT_INTERIM_INTERVAL_TYPE, value));
}
pub fn lookup_acct_interim_interval(packet: &Packet) -> Option<Result<u32, AVPError>> {
packet
.lookup(ACCT_INTERIM_INTERVAL_TYPE)
.map(|v| v.encode_u32())
}
pub fn lookup_all_acct_interim_interval(packet: &Packet) -> Result<Vec<u32>, AVPError> {
let mut vec = Vec::new();
for avp in packet.lookup_all(ACCT_INTERIM_INTERVAL_TYPE) {
vec.push(avp.encode_u32()?)
}
Ok(vec)
}
pub const NAS_PORT_ID_TYPE: AVPType = 87;
pub fn delete_nas_port_id(packet: &mut Packet) {
packet.delete(NAS_PORT_ID_TYPE);
}
pub fn add_nas_port_id(packet: &mut Packet, value: &str) {
packet.add(AVP::from_string(NAS_PORT_ID_TYPE, value));
}
pub fn lookup_nas_port_id(packet: &Packet) -> Option<Result<String, AVPError>> {
packet.lookup(NAS_PORT_ID_TYPE).map(|v| v.encode_string())
}
pub fn lookup_all_nas_port_id(packet: &Packet) -> Result<Vec<String>, AVPError> {
let mut vec = Vec::new();
for avp in packet.lookup_all(NAS_PORT_ID_TYPE) {
vec.push(avp.encode_string()?)
}
Ok(vec)
}
pub const FRAMED_POOL_TYPE: AVPType = 88;
pub fn delete_framed_pool(packet: &mut Packet) {
packet.delete(FRAMED_POOL_TYPE);
}
pub fn add_framed_pool(packet: &mut Packet, value: &str) {
packet.add(AVP::from_string(FRAMED_POOL_TYPE, value));
}
pub fn lookup_framed_pool(packet: &Packet) -> Option<Result<String, AVPError>> {
packet.lookup(FRAMED_POOL_TYPE).map(|v| v.encode_string())
}
pub fn lookup_all_framed_pool(packet: &Packet) -> Result<Vec<String>, AVPError> {
let mut vec = Vec::new();
for avp in packet.lookup_all(FRAMED_POOL_TYPE) {
vec.push(avp.encode_string()?)
}
Ok(vec)
}