async_snmp/notification/
types.rs1use bytes::Bytes;
6
7use crate::message::SecurityLevel;
8use crate::v3::{AuthProtocol, LocalizedKey, PrivKey, PrivProtocol};
9
10#[derive(Clone)]
14pub struct UsmUserConfig {
15 pub username: Bytes,
17 pub auth: Option<(AuthProtocol, Vec<u8>)>,
19 pub privacy: Option<(PrivProtocol, Vec<u8>)>,
21}
22
23impl UsmUserConfig {
24 pub fn new(username: impl Into<Bytes>) -> Self {
26 Self {
27 username: username.into(),
28 auth: None,
29 privacy: None,
30 }
31 }
32
33 pub fn auth(mut self, protocol: AuthProtocol, password: &[u8]) -> Self {
35 self.auth = Some((protocol, password.to_vec()));
36 self
37 }
38
39 pub fn privacy(mut self, protocol: PrivProtocol, password: &[u8]) -> Self {
41 self.privacy = Some((protocol, password.to_vec()));
42 self
43 }
44
45 pub fn security_level(&self) -> SecurityLevel {
47 match (&self.auth, &self.privacy) {
48 (None, _) => SecurityLevel::NoAuthNoPriv,
49 (Some(_), None) => SecurityLevel::AuthNoPriv,
50 (Some(_), Some(_)) => SecurityLevel::AuthPriv,
51 }
52 }
53
54 pub(crate) fn derive_keys(&self, engine_id: &[u8]) -> DerivedKeys {
56 let auth_key = self.auth.as_ref().map(|(protocol, password)| {
57 LocalizedKey::from_password(*protocol, password, engine_id)
58 });
59
60 let priv_key = match (&self.auth, &self.privacy) {
61 (Some((auth_protocol, _)), Some((priv_protocol, priv_password))) => Some(
62 PrivKey::from_password(*auth_protocol, *priv_protocol, priv_password, engine_id),
63 ),
64 _ => None,
65 };
66
67 DerivedKeys { auth_key, priv_key }
68 }
69}
70
71impl std::fmt::Debug for UsmUserConfig {
72 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73 f.debug_struct("UsmUserConfig")
74 .field("username", &String::from_utf8_lossy(&self.username))
75 .field("auth", &self.auth.as_ref().map(|(p, _)| p))
76 .field("privacy", &self.privacy.as_ref().map(|(p, _)| p))
77 .finish()
78 }
79}
80
81pub(crate) struct DerivedKeys {
85 pub auth_key: Option<LocalizedKey>,
87 pub priv_key: Option<PrivKey>,
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94
95 #[test]
96 fn test_usm_user_config_no_auth() {
97 let config = UsmUserConfig::new(Bytes::from_static(b"testuser"));
98 assert_eq!(config.security_level(), SecurityLevel::NoAuthNoPriv);
99 assert!(config.auth.is_none());
100 assert!(config.privacy.is_none());
101 }
102
103 #[test]
104 fn test_usm_user_config_auth_only() {
105 let config = UsmUserConfig::new(Bytes::from_static(b"testuser"))
106 .auth(AuthProtocol::Sha1, b"password123");
107 assert_eq!(config.security_level(), SecurityLevel::AuthNoPriv);
108 assert!(config.auth.is_some());
109 assert!(config.privacy.is_none());
110 }
111
112 #[test]
113 fn test_usm_user_config_auth_priv() {
114 let config = UsmUserConfig::new(Bytes::from_static(b"testuser"))
115 .auth(AuthProtocol::Sha256, b"authpass")
116 .privacy(PrivProtocol::Aes128, b"privpass");
117 assert_eq!(config.security_level(), SecurityLevel::AuthPriv);
118 assert!(config.auth.is_some());
119 assert!(config.privacy.is_some());
120 }
121
122 #[test]
123 fn test_usm_user_config_derive_keys() {
124 let config = UsmUserConfig::new(Bytes::from_static(b"testuser"))
125 .auth(AuthProtocol::Sha1, b"password123");
126
127 let engine_id = b"test-engine-id";
128 let keys = config.derive_keys(engine_id);
129
130 assert!(keys.auth_key.is_some());
131 assert!(keys.priv_key.is_none());
132 }
133
134 #[test]
135 fn test_usm_user_config_derive_keys_with_privacy() {
136 let config = UsmUserConfig::new(Bytes::from_static(b"testuser"))
137 .auth(AuthProtocol::Sha256, b"authpass")
138 .privacy(PrivProtocol::Aes128, b"privpass");
139
140 let engine_id = b"test-engine-id";
141 let keys = config.derive_keys(engine_id);
142
143 assert!(keys.auth_key.is_some());
144 assert!(keys.priv_key.is_some());
145 }
146}