Skip to content

Commit

Permalink
Merge branch 'release/v0.4.3'
Browse files Browse the repository at this point in the history
See CHANGELOG.md for all changes introduced in this release
  • Loading branch information
MikhailMS committed Mar 24, 2024
2 parents d017879 + 56aef22 commit ac13470
Show file tree
Hide file tree
Showing 9 changed files with 287 additions and 55 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/rust-radius.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
strategy:
fail-fast: false
matrix:
rust: [1.63.0, 1.64.0, 1.65.0, 1.66.1, 1.67.1, 1.68.2, 1.69.0, 1.70.0, 1.71.0, 1.71.1]
rust: [1.65.0, 1.66.1, 1.67.1, 1.68.2, 1.69.0, 1.70.0, 1.71.0, 1.71.1, 1.72.0, 1.72.1, 1.73.0, 1.74.0, 1.74.1, 1.75.0, 1.76.0, 1.77.0]
os: [ubuntu-20.04]
steps:

Expand All @@ -43,7 +43,7 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: install
args: --debug cargo-make --version 0.30.0
args: --debug cargo-make --version 0.22.2

- name: MODERN -- Build
run: cargo build --verbose
Expand Down Expand Up @@ -81,7 +81,7 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: install
args: --debug cargo-make --version 0.35.0
args: --debug cargo-make

- name: Nightly Rust -- Install tarpaulin
uses: actions-rs/cargo@v1
Expand Down
29 changes: 26 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
=============
# v0.4.3 (24 Mar 2024)

This release fixes issues reported in:
* [#28](/../../issues/28) (thanks to CoderChristopher for reporting and suggesting the solution)
* [#27](/../../issues/27)

## What's new
* Added `1.72.0, 1.72.1,1.73.0, 1.74.0, 1.74.1, 1.75.0, 1.76.0, 1.77.0` Rust versions to Action pipeline
* Incorporated [!29](/../../pull/29) to support addition of multiple dictionary files to a single `Dictionary` instance via new `add_file` function (Fixes [#27](/../../issues/27))

## What's removed or deprecated
* Removed `1.63.0 & 1.64.0` Rust versions from Action pipeline as they were failing to install `cargo-make` (those versions are still supported by library)

## What's changed
* Changed `initialise_packet_from_bytes` function of `radius_packet` to: (Fixes [#28](/../../issues/28))
* Handle packets of the length less than 20 or more than 4096 octets - returns `RadiusError` (to comply with [RFC2865](https://datatracker.ietf.org/doc/html/rfc2865))
* Derive packet length from `RadiusPacket` (Length field) instead of relying on `bytes.len()`
* If derived packet length is greater than `bytes.len()` - returns `RadiusError` (to comply with [RFC2865](https://datatracker.ietf.org/doc/html/rfc2865))
* Fixed incorrect tests in `protocol/host.rs` (flagged by the changed above)


=============
# v0.4.2 (05 Aug 2023)

Expand All @@ -16,14 +38,15 @@ This release fixes some outstanding items and, hopefully, makes it's easier to u
* Remove validation in `verify_original_value` for `ByteString` & `Concat` because it is not really possible to validate those values once received

## What's changed
* Closes #17
* Closes [#17](/../../issues/17)
* Fix for `timestamp_to_bytes` function - it was incorrectly expecting `u64` while RADIUS expects timestamps to be `u32`
* `verify_original_value` function now handles verify for `Integer64` & `InterfaceId` data types
* `original_string_value` function now handles retrieval of string value for `IPv4Prefix` & `InterfaceId` data types
* Functions to encode to/decode from `IPv4` bytes now also handle values with prefix/subnet
* Functions to encode to/decode from `IPv6` bytes now also handle values with prefix/subnet
* Not related to RADIUS implementation - Github Action CI/CD add support for newer Rust versions and drop support for older versions (because unfortunately Action fails on those)


=============
# v0.4.1 (10 Aug 2022)

Expand All @@ -45,7 +68,7 @@ This is small release/patch fixing a few bits here & there
* `rand`, `0.7.3` --> `0.8.5`
* `thiserror`, `1.0.23` --> `1.0.32`
* `log` library is moved into `dev-dependencies` and bumped to `0.4.17`
* Added code from PR #24 - ensure dictionary parser not failing when file has tabs as well as whitespaces
* Added code from PR [!24](/../../pull/24) - ensure dictionary parser not failing when file has tabs as well as whitespaces


=============
Expand All @@ -61,7 +84,7 @@ Got a couple of PRs & issues raised with some of them introducing breaking chang

## What's changed
* Breaking change - Changed **encrypt_data()** function signature, so **data** parameter is now of type **&[u8]** instead of **&str**. Was reported in [#4](/../../issues/4) by Istvan91
* Breaking change - RADIUS packet creation now doesn't require **Vec<RadiusAttribute>**. To set attributes for packet, call **set_attributes()** function. For examples have a look at **examples/*_client.rs** (Fixes #11)
* Breaking change - RADIUS packet creation now doesn't require **Vec<RadiusAttribute>**. To set attributes for packet, call **set_attributes()** function. For examples have a look at **examples/*_client.rs** (Fixes [#11](/../../issues/11))
* Rewrote **encrypt_data()** a bit to remove unneeded allocations (thanks to Istvan91 [!2](/../../pull/2))
* Rewrote **decrypt_data()** a bit to remove unneeded allocations (thanks to Istvan91 [!2](/../../pull/2))

Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
authors = ["MikhailMS <1488maiklm@gmail.com>"]
categories = ["network-programming"]
description = "Pure Rust implementation of RADIUS Server/Client"
documentation = "https://docs.rs/radius-rust/0.4.2"
documentation = "https://docs.rs/radius-rust/0.4.3"
edition = "2018"
include = [
"Cargo.toml",
Expand All @@ -20,7 +20,7 @@ license = "MIT"
name = "radius-rust"
readme = "README.md"
repository = "https://github.com/MikhailMS/rust-radius"
version = "0.4.2"
version = "0.4.3"

[features]
# Default doesn\t include anythin - keep it simple
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ Rationale behind this project:
## Installation
```
[dependencies]
radius-rust = "0.4.2"
radius-rust = "0.4.3"
OR if you are planning to build Async RADIUS Client/Server
[dependencies]
radius-rust = { version = "0.4.2", features = ["async-radius"] }
radius-rust = { version = "0.4.3", features = ["async-radius"] }
```


Expand Down
Empty file.
169 changes: 149 additions & 20 deletions src/protocol/dictionary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,26 +137,19 @@ impl Dictionary {
let mut attributes: Vec<DictionaryAttribute> = Vec::new();
let mut values: Vec<DictionaryValue> = Vec::new();
let mut vendors: Vec<DictionaryVendor> = Vec::new();
let mut vendor_name: String = String::new();

let reader = io::BufReader::new(File::open(file_path).map_err(|error| RadiusError::MalformedDictionaryError { error })?);
let lines = reader.lines()
.filter_map(Result::ok)
.filter(|line| !line.is_empty())
.filter(|line| !line.contains(&COMMENT_PREFIX));

for line in lines {
let parsed_line: Vec<&str> = line.split_whitespace().filter(|&item| !item.is_empty()).collect();
match parsed_line[0] {
"ATTRIBUTE" => parse_attribute(parsed_line, &vendor_name, &mut attributes),
"VALUE" => parse_value(parsed_line, &vendor_name, &mut values),
"VENDOR" => parse_vendor(parsed_line, &mut vendors),
"BEGIN-VENDOR" => { vendor_name.insert_str(0, parsed_line[1]) },
"END-VENDOR" => { vendor_name.clear() },
_ => continue
}
};
Ok(Dictionary { attributes, values, vendors })

match parse_file(file_path, &mut attributes, &mut values, &mut vendors) {
Ok(()) => Ok(Dictionary { attributes, values, vendors }),
Err(error) => Err(error)
}
}

/// Adds a dictionary file to existing Dictionary
///
/// Processes attributes, values and vendors from supplied dictionary file
/// and adds them to existing attributes, values and vendors
pub fn add_file(&mut self, file_path: &str) -> Result<(), RadiusError> {
parse_file(file_path, &mut self.attributes, &mut self.values, &mut self.vendors)
}

/// Returns parsed DictionaryAttributes
Expand Down Expand Up @@ -198,6 +191,30 @@ fn assign_attribute_type(code_type: &str) -> Option<SupportedAttributeTypes> {
}
}

fn parse_file(file_path: &str, attributes: &mut Vec<DictionaryAttribute>, values: &mut Vec<DictionaryValue>, vendors: &mut Vec<DictionaryVendor>) -> Result<(), RadiusError> {
let mut vendor_name: String = String::new();

let reader = io::BufReader::new(File::open(file_path).map_err(|error| RadiusError::MalformedDictionaryError { error })?);
let lines = reader.lines()
.filter_map(Result::ok)
.filter(|line| !line.is_empty())
.filter(|line| !line.contains(&COMMENT_PREFIX));

for line in lines {
let parsed_line: Vec<&str> = line.split_whitespace().filter(|&item| !item.is_empty()).collect();
match parsed_line[0] {
"ATTRIBUTE" => parse_attribute(parsed_line, &vendor_name, attributes),
"VALUE" => parse_value(parsed_line, &vendor_name, values),
"VENDOR" => parse_vendor(parsed_line, vendors),
"BEGIN-VENDOR" => { vendor_name.insert_str(0, parsed_line[1]) },
"END-VENDOR" => { vendor_name.clear() },
_ => continue
}
};

Ok(())
}

fn parse_attribute(parsed_line: Vec<&str>, vendor_name: &str, attributes: &mut Vec<DictionaryAttribute>) {
if let Ok(code) = parsed_line[2].parse::<u8>() {
attributes.push(DictionaryAttribute {
Expand Down Expand Up @@ -341,4 +358,116 @@ mod tests {
let expected_dict = Dictionary { attributes, values, vendors };
assert_eq!(dict, expected_dict)
}

#[test]
fn test_add_file() {
let empty_dictionary_path = "./dict_examples/empty_test_dictionary_dict";
let dictionary_path = "./dict_examples/test_dictionary_dict";

let mut dict = Dictionary::from_file(empty_dictionary_path).unwrap();
dict.add_file(dictionary_path).unwrap();

let mut attributes: Vec<DictionaryAttribute> = Vec::new();
attributes.push(DictionaryAttribute {
name: "User-Name".to_string(),
vendor_name: "".to_string(),
code: 1,
code_type: Some(SupportedAttributeTypes::AsciiString)
});
attributes.push(DictionaryAttribute {
name: "NAS-IP-Address".to_string(),
vendor_name: "".to_string(),
code: 4,
code_type: Some(SupportedAttributeTypes::IPv4Addr)
});
attributes.push(DictionaryAttribute {
name: "NAS-Port-Id".to_string(),
vendor_name: "".to_string(),
code: 5,
code_type: Some(SupportedAttributeTypes::Integer)
});
attributes.push(DictionaryAttribute {
name: "Framed-Protocol".to_string(),
vendor_name: "".to_string(),
code: 7,
code_type: Some(SupportedAttributeTypes::Integer)
});
attributes.push(DictionaryAttribute {
name: "Chargeable-User-Identity".to_string(),
vendor_name: "".to_string(),
code: 89,
code_type: Some(SupportedAttributeTypes::ByteString)
});
attributes.push(DictionaryAttribute {
name: "Delegated-IPv6-Prefix".to_string(),
vendor_name: "".to_string(),
code: 123,
code_type: Some(SupportedAttributeTypes::IPv6Prefix)
});
attributes.push(DictionaryAttribute {
name: "MIP6-Feature-Vector".to_string(),
vendor_name: "".to_string(),
code: 124,
code_type: Some(SupportedAttributeTypes::Integer64)
});
attributes.push(DictionaryAttribute {
name: "Mobile-Node-Identifier".to_string(),
vendor_name: "".to_string(),
code: 145,
code_type: Some(SupportedAttributeTypes::ByteString)
});
attributes.push(DictionaryAttribute {
name: "PMIP6-Home-Interface-ID".to_string(),
vendor_name: "".to_string(),
code: 153,
code_type: Some(SupportedAttributeTypes::InterfaceId)
});
attributes.push(DictionaryAttribute {
name: "PMIP6-Home-IPv4-HoA".to_string(),
vendor_name: "".to_string(),
code: 155,
code_type: Some(SupportedAttributeTypes::IPv4Prefix)
});
attributes.push(DictionaryAttribute {
name: "Somevendor-Name".to_string(),
vendor_name: "Somevendor".to_string(),
code: 1,
code_type: Some(SupportedAttributeTypes::AsciiString)
});
attributes.push(DictionaryAttribute {
name: "Somevendor-Number".to_string(),
vendor_name: "Somevendor".to_string(),
code: 2,
code_type: Some(SupportedAttributeTypes::Integer)
});
attributes.push(DictionaryAttribute {
name: "Class".to_string(),
vendor_name: "".to_string(),
code: 25,
code_type: Some(SupportedAttributeTypes::ByteString)
});

let mut values: Vec<DictionaryValue> = Vec::new();
values.push(DictionaryValue {
attribute_name: "Framed-Protocol".to_string(),
value_name: "PPP".to_string(),
vendor_name: "".to_string(),
value: "1".to_string()
});
values.push(DictionaryValue {
attribute_name: "Somevendor-Number".to_string(),
value_name: "Two".to_string(),
vendor_name: "Somevendor".to_string(),
value: "2".to_string()
});

let mut vendors: Vec<DictionaryVendor> = Vec::new();
vendors.push(DictionaryVendor {
name: "Somevendor".to_string(),
id: 10,
});

let expected_dict = Dictionary { attributes, values, vendors };
assert_eq!(dict, expected_dict)
}
}
6 changes: 3 additions & 3 deletions src/protocol/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ mod tests {
let dictionary = Dictionary::from_file("./dict_examples/integration_dict").unwrap();
let host = Host::initialise_host(1812, 1813, 3799, dictionary);

let packet_bytes = [4, 43, 0, 83, 215, 189, 213, 172, 57, 94, 141, 70, 134, 121, 101, 57, 187, 220, 227, 73, 4, 6, 192, 168, 1, 10, 5, 6, 0, 0, 0, 0, 32, 10, 116, 114, 105, 108, 108, 105, 97, 110, 30, 19, 48, 48, 45, 48, 52, 45, 53, 70, 45, 48, 48, 45, 48, 70, 45, 68, 49, 31, 19, 48, 48, 45, 48, 49, 45, 50, 52, 45, 56, 48, 45, 66, 51, 45, 57, 67, 8, 6, 10, 0, 0, 100];
let packet_bytes = [4, 43, 0, 86, 215, 189, 213, 172, 57, 94, 141, 70, 134, 121, 101, 57, 187, 220, 227, 73, 4, 6, 192, 168, 1, 10, 5, 6, 0, 0, 0, 0, 32, 10, 116, 114, 105, 108, 108, 105, 97, 110, 30, 19, 48, 48, 45, 48, 52, 45, 53, 70, 45, 48, 48, 45, 48, 70, 45, 68, 49, 31, 19, 48, 48, 45, 48, 49, 45, 50, 52, 45, 56, 48, 45, 66, 51, 45, 57, 67, 8, 6, 10, 0, 0, 100];

match host.verify_packet_attributes(&packet_bytes) {
Err(_err) => {
Expand All @@ -209,7 +209,7 @@ mod tests {
let dictionary = Dictionary::from_file("./dict_examples/integration_dict").unwrap();
let host = Host::initialise_host(1812, 1813, 3799, dictionary);

let packet_bytes = [4, 43, 0, 82, 215, 189, 213, 172, 57, 94, 141, 70, 134, 121, 101, 57, 187, 220, 227, 73, 4, 5, 192, 168, 10, 5, 6, 0, 0, 0, 0, 32, 10, 116, 114, 105, 108, 108, 105, 97, 110, 30, 19, 48, 48, 45, 48, 52, 45, 53, 70, 45, 48, 48, 45, 48, 70, 45, 68, 49, 31, 19, 48, 48, 45, 48, 49, 45, 50, 52, 45, 56, 48, 45, 66, 51, 45, 57, 67, 8, 6, 10, 0, 0, 100];
let packet_bytes = [4, 43, 0, 85, 215, 189, 213, 172, 57, 94, 141, 70, 134, 121, 101, 57, 187, 220, 227, 73, 4, 5, 192, 168, 10, 5, 6, 0, 0, 0, 0, 32, 10, 116, 114, 105, 108, 108, 105, 97, 110, 30, 19, 48, 48, 45, 48, 52, 45, 53, 70, 45, 48, 48, 45, 48, 70, 45, 68, 49, 31, 19, 48, 48, 45, 48, 49, 45, 50, 52, 45, 56, 48, 45, 66, 51, 45, 57, 67, 8, 6, 10, 0, 0, 100];

match host.verify_packet_attributes(&packet_bytes) {
Err(err) => {
Expand Down Expand Up @@ -241,7 +241,7 @@ mod tests {
let host = Host::initialise_host(1812, 1813, 3799, dictionary);
let secret = "secret";

let packet_bytes = [4, 43, 0, 83, 215, 189, 213, 172, 57, 94, 141, 70, 134, 121, 101, 57, 187, 220, 227, 73, 4, 6, 192, 168, 1, 10, 5, 6, 0, 0, 0, 0, 32, 10, 116, 114, 105, 108, 108, 105, 97, 110, 30, 19, 48, 48, 45, 48, 52, 45, 53, 70, 45, 48, 48, 45, 48, 70, 45, 68, 49, 31, 19, 48, 48, 45, 48, 49, 45, 50, 52, 45, 56, 48, 45, 66, 51, 45, 57, 67, 8, 6, 10, 0, 0, 100];
let packet_bytes = [4, 43, 0, 86, 215, 189, 213, 172, 57, 94, 141, 70, 134, 121, 101, 57, 187, 220, 227, 73, 4, 6, 192, 168, 1, 10, 5, 6, 0, 0, 0, 0, 32, 10, 116, 114, 105, 108, 108, 105, 97, 110, 30, 19, 48, 48, 45, 48, 52, 45, 53, 70, 45, 48, 48, 45, 48, 70, 45, 68, 49, 31, 19, 48, 48, 45, 48, 49, 45, 50, 52, 45, 56, 48, 45, 66, 51, 45, 57, 67, 8, 6, 10, 0, 0, 100];

match host.verify_message_authenticator(&secret, &packet_bytes) {
Err(err) => {
Expand Down
Loading

0 comments on commit ac13470

Please sign in to comment.