Skip to content

Commit ac13470

Browse files
committed
Merge branch 'release/v0.4.3'
See CHANGELOG.md for all changes introduced in this release
2 parents d017879 + 56aef22 commit ac13470

File tree

9 files changed

+287
-55
lines changed

9 files changed

+287
-55
lines changed

.github/workflows/rust-radius.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
strategy:
2828
fail-fast: false
2929
matrix:
30-
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]
30+
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]
3131
os: [ubuntu-20.04]
3232
steps:
3333

@@ -43,7 +43,7 @@ jobs:
4343
uses: actions-rs/cargo@v1
4444
with:
4545
command: install
46-
args: --debug cargo-make --version 0.30.0
46+
args: --debug cargo-make --version 0.22.2
4747

4848
- name: MODERN -- Build
4949
run: cargo build --verbose
@@ -81,7 +81,7 @@ jobs:
8181
uses: actions-rs/cargo@v1
8282
with:
8383
command: install
84-
args: --debug cargo-make --version 0.35.0
84+
args: --debug cargo-make
8585

8686
- name: Nightly Rust -- Install tarpaulin
8787
uses: actions-rs/cargo@v1

CHANGELOG.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,25 @@
1+
=============
2+
# v0.4.3 (24 Mar 2024)
3+
4+
This release fixes issues reported in:
5+
* [#28](/../../issues/28) (thanks to CoderChristopher for reporting and suggesting the solution)
6+
* [#27](/../../issues/27)
7+
8+
## What's new
9+
* 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
10+
* 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))
11+
12+
## What's removed or deprecated
13+
* 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)
14+
15+
## What's changed
16+
* Changed `initialise_packet_from_bytes` function of `radius_packet` to: (Fixes [#28](/../../issues/28))
17+
* 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))
18+
* Derive packet length from `RadiusPacket` (Length field) instead of relying on `bytes.len()`
19+
* If derived packet length is greater than `bytes.len()` - returns `RadiusError` (to comply with [RFC2865](https://datatracker.ietf.org/doc/html/rfc2865))
20+
* Fixed incorrect tests in `protocol/host.rs` (flagged by the changed above)
21+
22+
123
=============
224
# v0.4.2 (05 Aug 2023)
325

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

1840
## What's changed
19-
* Closes #17
41+
* Closes [#17](/../../issues/17)
2042
* Fix for `timestamp_to_bytes` function - it was incorrectly expecting `u64` while RADIUS expects timestamps to be `u32`
2143
* `verify_original_value` function now handles verify for `Integer64` & `InterfaceId` data types
2244
* `original_string_value` function now handles retrieval of string value for `IPv4Prefix` & `InterfaceId` data types
2345
* Functions to encode to/decode from `IPv4` bytes now also handle values with prefix/subnet
2446
* Functions to encode to/decode from `IPv6` bytes now also handle values with prefix/subnet
2547
* 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)
2648

49+
2750
=============
2851
# v0.4.1 (10 Aug 2022)
2952

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

5073

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

6285
## What's changed
6386
* 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
64-
* 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)
87+
* 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))
6588
* Rewrote **encrypt_data()** a bit to remove unneeded allocations (thanks to Istvan91 [!2](/../../pull/2))
6689
* Rewrote **decrypt_data()** a bit to remove unneeded allocations (thanks to Istvan91 [!2](/../../pull/2))
6790

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
authors = ["MikhailMS <[email protected]>"]
33
categories = ["network-programming"]
44
description = "Pure Rust implementation of RADIUS Server/Client"
5-
documentation = "https://docs.rs/radius-rust/0.4.2"
5+
documentation = "https://docs.rs/radius-rust/0.4.3"
66
edition = "2018"
77
include = [
88
"Cargo.toml",
@@ -20,7 +20,7 @@ license = "MIT"
2020
name = "radius-rust"
2121
readme = "README.md"
2222
repository = "https://github.com/MikhailMS/rust-radius"
23-
version = "0.4.2"
23+
version = "0.4.3"
2424

2525
[features]
2626
# Default doesn\t include anythin - keep it simple

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ Rationale behind this project:
2929
## Installation
3030
```
3131
[dependencies]
32-
radius-rust = "0.4.2"
32+
radius-rust = "0.4.3"
3333
3434
OR if you are planning to build Async RADIUS Client/Server
3535
3636
[dependencies]
37-
radius-rust = { version = "0.4.2", features = ["async-radius"] }
37+
radius-rust = { version = "0.4.3", features = ["async-radius"] }
3838
```
3939

4040

dict_examples/empty_test_dictionary_dict

Whitespace-only changes.

src/protocol/dictionary.rs

Lines changed: 149 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -137,26 +137,19 @@ impl Dictionary {
137137
let mut attributes: Vec<DictionaryAttribute> = Vec::new();
138138
let mut values: Vec<DictionaryValue> = Vec::new();
139139
let mut vendors: Vec<DictionaryVendor> = Vec::new();
140-
let mut vendor_name: String = String::new();
141-
142-
let reader = io::BufReader::new(File::open(file_path).map_err(|error| RadiusError::MalformedDictionaryError { error })?);
143-
let lines = reader.lines()
144-
.filter_map(Result::ok)
145-
.filter(|line| !line.is_empty())
146-
.filter(|line| !line.contains(&COMMENT_PREFIX));
147-
148-
for line in lines {
149-
let parsed_line: Vec<&str> = line.split_whitespace().filter(|&item| !item.is_empty()).collect();
150-
match parsed_line[0] {
151-
"ATTRIBUTE" => parse_attribute(parsed_line, &vendor_name, &mut attributes),
152-
"VALUE" => parse_value(parsed_line, &vendor_name, &mut values),
153-
"VENDOR" => parse_vendor(parsed_line, &mut vendors),
154-
"BEGIN-VENDOR" => { vendor_name.insert_str(0, parsed_line[1]) },
155-
"END-VENDOR" => { vendor_name.clear() },
156-
_ => continue
157-
}
158-
};
159-
Ok(Dictionary { attributes, values, vendors })
140+
141+
match parse_file(file_path, &mut attributes, &mut values, &mut vendors) {
142+
Ok(()) => Ok(Dictionary { attributes, values, vendors }),
143+
Err(error) => Err(error)
144+
}
145+
}
146+
147+
/// Adds a dictionary file to existing Dictionary
148+
///
149+
/// Processes attributes, values and vendors from supplied dictionary file
150+
/// and adds them to existing attributes, values and vendors
151+
pub fn add_file(&mut self, file_path: &str) -> Result<(), RadiusError> {
152+
parse_file(file_path, &mut self.attributes, &mut self.values, &mut self.vendors)
160153
}
161154

162155
/// Returns parsed DictionaryAttributes
@@ -198,6 +191,30 @@ fn assign_attribute_type(code_type: &str) -> Option<SupportedAttributeTypes> {
198191
}
199192
}
200193

194+
fn parse_file(file_path: &str, attributes: &mut Vec<DictionaryAttribute>, values: &mut Vec<DictionaryValue>, vendors: &mut Vec<DictionaryVendor>) -> Result<(), RadiusError> {
195+
let mut vendor_name: String = String::new();
196+
197+
let reader = io::BufReader::new(File::open(file_path).map_err(|error| RadiusError::MalformedDictionaryError { error })?);
198+
let lines = reader.lines()
199+
.filter_map(Result::ok)
200+
.filter(|line| !line.is_empty())
201+
.filter(|line| !line.contains(&COMMENT_PREFIX));
202+
203+
for line in lines {
204+
let parsed_line: Vec<&str> = line.split_whitespace().filter(|&item| !item.is_empty()).collect();
205+
match parsed_line[0] {
206+
"ATTRIBUTE" => parse_attribute(parsed_line, &vendor_name, attributes),
207+
"VALUE" => parse_value(parsed_line, &vendor_name, values),
208+
"VENDOR" => parse_vendor(parsed_line, vendors),
209+
"BEGIN-VENDOR" => { vendor_name.insert_str(0, parsed_line[1]) },
210+
"END-VENDOR" => { vendor_name.clear() },
211+
_ => continue
212+
}
213+
};
214+
215+
Ok(())
216+
}
217+
201218
fn parse_attribute(parsed_line: Vec<&str>, vendor_name: &str, attributes: &mut Vec<DictionaryAttribute>) {
202219
if let Ok(code) = parsed_line[2].parse::<u8>() {
203220
attributes.push(DictionaryAttribute {
@@ -341,4 +358,116 @@ mod tests {
341358
let expected_dict = Dictionary { attributes, values, vendors };
342359
assert_eq!(dict, expected_dict)
343360
}
361+
362+
#[test]
363+
fn test_add_file() {
364+
let empty_dictionary_path = "./dict_examples/empty_test_dictionary_dict";
365+
let dictionary_path = "./dict_examples/test_dictionary_dict";
366+
367+
let mut dict = Dictionary::from_file(empty_dictionary_path).unwrap();
368+
dict.add_file(dictionary_path).unwrap();
369+
370+
let mut attributes: Vec<DictionaryAttribute> = Vec::new();
371+
attributes.push(DictionaryAttribute {
372+
name: "User-Name".to_string(),
373+
vendor_name: "".to_string(),
374+
code: 1,
375+
code_type: Some(SupportedAttributeTypes::AsciiString)
376+
});
377+
attributes.push(DictionaryAttribute {
378+
name: "NAS-IP-Address".to_string(),
379+
vendor_name: "".to_string(),
380+
code: 4,
381+
code_type: Some(SupportedAttributeTypes::IPv4Addr)
382+
});
383+
attributes.push(DictionaryAttribute {
384+
name: "NAS-Port-Id".to_string(),
385+
vendor_name: "".to_string(),
386+
code: 5,
387+
code_type: Some(SupportedAttributeTypes::Integer)
388+
});
389+
attributes.push(DictionaryAttribute {
390+
name: "Framed-Protocol".to_string(),
391+
vendor_name: "".to_string(),
392+
code: 7,
393+
code_type: Some(SupportedAttributeTypes::Integer)
394+
});
395+
attributes.push(DictionaryAttribute {
396+
name: "Chargeable-User-Identity".to_string(),
397+
vendor_name: "".to_string(),
398+
code: 89,
399+
code_type: Some(SupportedAttributeTypes::ByteString)
400+
});
401+
attributes.push(DictionaryAttribute {
402+
name: "Delegated-IPv6-Prefix".to_string(),
403+
vendor_name: "".to_string(),
404+
code: 123,
405+
code_type: Some(SupportedAttributeTypes::IPv6Prefix)
406+
});
407+
attributes.push(DictionaryAttribute {
408+
name: "MIP6-Feature-Vector".to_string(),
409+
vendor_name: "".to_string(),
410+
code: 124,
411+
code_type: Some(SupportedAttributeTypes::Integer64)
412+
});
413+
attributes.push(DictionaryAttribute {
414+
name: "Mobile-Node-Identifier".to_string(),
415+
vendor_name: "".to_string(),
416+
code: 145,
417+
code_type: Some(SupportedAttributeTypes::ByteString)
418+
});
419+
attributes.push(DictionaryAttribute {
420+
name: "PMIP6-Home-Interface-ID".to_string(),
421+
vendor_name: "".to_string(),
422+
code: 153,
423+
code_type: Some(SupportedAttributeTypes::InterfaceId)
424+
});
425+
attributes.push(DictionaryAttribute {
426+
name: "PMIP6-Home-IPv4-HoA".to_string(),
427+
vendor_name: "".to_string(),
428+
code: 155,
429+
code_type: Some(SupportedAttributeTypes::IPv4Prefix)
430+
});
431+
attributes.push(DictionaryAttribute {
432+
name: "Somevendor-Name".to_string(),
433+
vendor_name: "Somevendor".to_string(),
434+
code: 1,
435+
code_type: Some(SupportedAttributeTypes::AsciiString)
436+
});
437+
attributes.push(DictionaryAttribute {
438+
name: "Somevendor-Number".to_string(),
439+
vendor_name: "Somevendor".to_string(),
440+
code: 2,
441+
code_type: Some(SupportedAttributeTypes::Integer)
442+
});
443+
attributes.push(DictionaryAttribute {
444+
name: "Class".to_string(),
445+
vendor_name: "".to_string(),
446+
code: 25,
447+
code_type: Some(SupportedAttributeTypes::ByteString)
448+
});
449+
450+
let mut values: Vec<DictionaryValue> = Vec::new();
451+
values.push(DictionaryValue {
452+
attribute_name: "Framed-Protocol".to_string(),
453+
value_name: "PPP".to_string(),
454+
vendor_name: "".to_string(),
455+
value: "1".to_string()
456+
});
457+
values.push(DictionaryValue {
458+
attribute_name: "Somevendor-Number".to_string(),
459+
value_name: "Two".to_string(),
460+
vendor_name: "Somevendor".to_string(),
461+
value: "2".to_string()
462+
});
463+
464+
let mut vendors: Vec<DictionaryVendor> = Vec::new();
465+
vendors.push(DictionaryVendor {
466+
name: "Somevendor".to_string(),
467+
id: 10,
468+
});
469+
470+
let expected_dict = Dictionary { attributes, values, vendors };
471+
assert_eq!(dict, expected_dict)
472+
}
344473
}

src/protocol/host.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ mod tests {
194194
let dictionary = Dictionary::from_file("./dict_examples/integration_dict").unwrap();
195195
let host = Host::initialise_host(1812, 1813, 3799, dictionary);
196196

197-
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];
197+
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];
198198

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

212-
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];
212+
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];
213213

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

244-
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];
244+
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];
245245

246246
match host.verify_message_authenticator(&secret, &packet_bytes) {
247247
Err(err) => {

0 commit comments

Comments
 (0)