1use std::sync::Arc;
2use crate::{
3 dictionary::Dictionary,
4 packet::{RadiusAttribute, RadiusPacket},
5};
6use md5;
7
8pub fn build_response_with_auth(
10 mut packet: RadiusPacket,
11 request_authenticator: [u8; 16],
12 secret: &str,
13) -> RadiusPacket {
14 let mut buf = Vec::new();
15 buf.push(packet.code);
16 buf.push(packet.identifier);
17 buf.extend_from_slice(&[0x00, 0x00]); buf.extend_from_slice(&request_authenticator);
19
20 for attr in &packet.attributes {
21 buf.push(attr.typ);
22 buf.push(attr.len);
23 buf.extend_from_slice(&attr.value);
24 }
25
26 let length = buf.len() as u16;
27 buf[2] = (length >> 8) as u8;
28 buf[3] = (length & 0xFF) as u8;
29
30 buf.extend_from_slice(secret.as_bytes());
31
32 let hash = md5::compute(&buf);
33 let mut authenticator = [0u8; 16];
34 authenticator.copy_from_slice(&hash.0);
35
36 packet.length = length;
37 packet.authenticator = authenticator;
38
39 packet
40}
41
42pub fn handle(packet: RadiusPacket, dict: Arc<Dictionary>) -> Result<RadiusPacket, String> {
44 println!("🔍 Handling RADIUS packet ID: {}", packet.identifier);
45
46 for attr in &packet.attributes {
47 let attr_code = attr.typ as u32;
48 match dict.attributes.get(&attr_code) {
49 Some(def) => {
50 let name = &def.name;
51 match std::str::from_utf8(&attr.value) {
52 Ok(s) => println!("→ {}: {}", name, s.trim()),
53 Err(_) => println!("→ {}: {:?}", name, attr.value),
54 }
55 }
56 None => println!("→ Unknown Attribute Type {}: {:?}", attr.typ, attr.value),
57 }
58 }
59
60 let mut attributes = vec![
61 RadiusAttribute::reply_message("Access granted via Rust RADIUS server."),
62 RadiusAttribute::session_timeout(3600),
63 RadiusAttribute::idle_timeout(300),
64 RadiusAttribute::wispr_bandwidth_max_up(512_000),
65 RadiusAttribute::wispr_bandwidth_max_down(1_000_000),
66 ];
67
68 if let Some(user_attr) = packet.attributes.iter().find(|a| a.typ == 1) {
70 if let Ok(username) = std::str::from_utf8(&user_attr.value) {
71 attributes.push(RadiusAttribute::user_name(username));
72 }
73 }
74
75 let accept = RadiusPacket::access_accept(packet.identifier, attributes);
76 let response = build_response_with_auth(accept, packet.authenticator, "test123");
77 Ok(response)
78}