ipmi_rs/app/auth/
get_channel_authentication_capabilities.rs

1use crate::connection::{Channel, IpmiCommand, Message, NetFn};
2
3use super::{AuthType, PrivilegeLevel};
4
5#[derive(Debug, Clone)]
6pub struct ChannelAuthenticationCapabilities {
7    pub channel_number: u8,
8    pub oem_proprietary: bool,
9    pub key: bool,
10    pub md5: bool,
11    pub md2: bool,
12    pub none: bool,
13    pub kg_status: bool,
14    pub per_message_authentication_enabled: bool,
15    pub user_level_authentication_enabled: bool,
16    pub non_null_usernames_enabled: bool,
17    pub null_usernames_enabled: bool,
18    pub anonymous_login_enabled: bool,
19    pub ipmi2_connections_supported: bool,
20    pub ipmi15_connections_supported: bool,
21    pub oem_id: [u8; 3],
22    pub oem_auxiliary_data: u8,
23}
24
25impl ChannelAuthenticationCapabilities {
26    pub fn best_auth(&self) -> Option<AuthType> {
27        let auth_type = if self.md5 {
28            AuthType::MD5
29        } else if self.md2 {
30            AuthType::MD2
31        } else if self.key {
32            AuthType::Key
33        } else if self.none {
34            AuthType::None
35        } else {
36            return None;
37        };
38        Some(auth_type)
39    }
40}
41
42#[derive(Debug, Clone)]
43pub struct GetChannelAuthenticationCapabilities {
44    channel_number: Channel,
45    privilege_level: PrivilegeLevel,
46}
47
48impl GetChannelAuthenticationCapabilities {
49    pub fn new(channel_number: Channel, privilege_level: PrivilegeLevel) -> Self {
50        Self {
51            channel_number,
52            privilege_level,
53        }
54    }
55}
56
57impl From<GetChannelAuthenticationCapabilities> for Message {
58    fn from(value: GetChannelAuthenticationCapabilities) -> Message {
59        Message::new_request(
60            NetFn::App,
61            0x38,
62            vec![
63                0x80 | value.channel_number.value(),
64                value.privilege_level.into(),
65            ],
66        )
67    }
68}
69
70impl IpmiCommand for GetChannelAuthenticationCapabilities {
71    type Output = ChannelAuthenticationCapabilities;
72
73    type Error = ();
74
75    fn parse_response(
76        completion_code: crate::connection::CompletionCode,
77        data: &[u8],
78    ) -> Result<Self::Output, crate::connection::ParseResponseError<Self::Error>> {
79        Self::check_cc_success(completion_code)?;
80
81        if data.len() < 7 {
82            return Err(crate::connection::ParseResponseError::NotEnoughData);
83        }
84
85        let channel_number = data[0];
86        let ipmi2_ext_cap = (data[1] & 0x80) == 0x80;
87
88        let oem_proprietary = (data[1] & 0x20) == 0x20;
89        let key = (data[1] & 0x10) == 0x10;
90        let md5 = (data[1] & 0x04) == 0x04;
91        let md2 = (data[1] & 0x02) == 0x02;
92        let none = (data[1] & 0x01) == 0x01;
93
94        let pma = (data[2] & 0x10) == 0x10;
95        let ula = (data[2] & 0x08) == 0x08;
96        let nnue = (data[2] & 0x04) == 0x04;
97        let nue = (data[2] & 0x02) == 0x02;
98        let ale = (data[2] & 0x01) == 0x01;
99
100        let (kg, v2, v15, oem_id, oem_aux) = if ipmi2_ext_cap {
101            if data.len() < 8 {
102                return Err(crate::connection::ParseResponseError::NotEnoughData);
103            }
104
105            let kg = (data[2] & 0x20) == 0x20;
106
107            let v2 = (data[3] & 0x02) == 0x02;
108            let v15 = (data[3] & 0x01) == 0x01;
109
110            let oem_id = [data[4], data[5], data[6]];
111            let oem_aux = data[7];
112            (kg, v2, v15, oem_id, oem_aux)
113        } else {
114            let oem_id = [data[3], data[4], data[5]];
115            let oem_aux = data[6];
116            (false, false, false, oem_id, oem_aux)
117        };
118
119        Ok(ChannelAuthenticationCapabilities {
120            channel_number,
121            oem_proprietary,
122            key,
123            md5,
124            md2,
125            none,
126            kg_status: kg,
127            per_message_authentication_enabled: !pma,
128            user_level_authentication_enabled: !ula,
129            non_null_usernames_enabled: nnue,
130            null_usernames_enabled: nue,
131            anonymous_login_enabled: ale,
132            ipmi2_connections_supported: v2,
133            ipmi15_connections_supported: v15,
134            oem_id,
135            oem_auxiliary_data: oem_aux,
136        })
137    }
138}