1 #[cfg(test)] 2 mod textattrs_test; 3 4 use crate::attributes::*; 5 use crate::checks::*; 6 use crate::error::*; 7 use crate::message::*; 8 9 use std::fmt; 10 11 const MAX_USERNAME_B: usize = 513; 12 const MAX_REALM_B: usize = 763; 13 const MAX_SOFTWARE_B: usize = 763; 14 const MAX_NONCE_B: usize = 763; 15 16 // Username represents USERNAME attribute. 17 // 18 // RFC 5389 Section 15.3 19 pub type Username = TextAttribute; 20 21 // Realm represents REALM attribute. 22 // 23 // RFC 5389 Section 15.7 24 pub type Realm = TextAttribute; 25 26 // Nonce represents NONCE attribute. 27 // 28 // RFC 5389 Section 15.8 29 pub type Nonce = TextAttribute; 30 31 // Software is SOFTWARE attribute. 32 // 33 // RFC 5389 Section 15.10 34 pub type Software = TextAttribute; 35 36 // TextAttribute is helper for adding and getting text attributes. 37 #[derive(Clone, Default)] 38 pub struct TextAttribute { 39 pub attr: AttrType, 40 pub text: String, 41 } 42 43 impl fmt::Display for TextAttribute { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 45 write!(f, "{}", self.text) 46 } 47 } 48 49 impl Setter for TextAttribute { 50 // add_to_as adds attribute with type t to m, checking maximum length. If max_len 51 // is less than 0, no check is performed. add_to(&self, m: &mut Message) -> Result<()>52 fn add_to(&self, m: &mut Message) -> Result<()> { 53 let text = self.text.as_bytes(); 54 let max_len = match self.attr { 55 ATTR_USERNAME => MAX_USERNAME_B, 56 ATTR_REALM => MAX_REALM_B, 57 ATTR_SOFTWARE => MAX_SOFTWARE_B, 58 ATTR_NONCE => MAX_NONCE_B, 59 _ => return Err(Error::Other(format!("Unsupported AttrType {}", self.attr))), 60 }; 61 62 check_overflow(self.attr, text.len(), max_len)?; 63 m.add(self.attr, text); 64 Ok(()) 65 } 66 } 67 68 impl Getter for TextAttribute { get_from(&mut self, m: &Message) -> Result<()>69 fn get_from(&mut self, m: &Message) -> Result<()> { 70 let attr = self.attr; 71 *self = TextAttribute::get_from_as(m, attr)?; 72 Ok(()) 73 } 74 } 75 76 impl TextAttribute { new(attr: AttrType, text: String) -> Self77 pub fn new(attr: AttrType, text: String) -> Self { 78 TextAttribute { attr, text } 79 } 80 81 // get_from_as gets t attribute from m and appends its value to reseted v. get_from_as(m: &Message, attr: AttrType) -> Result<Self>82 pub fn get_from_as(m: &Message, attr: AttrType) -> Result<Self> { 83 match attr { 84 ATTR_USERNAME => {} 85 ATTR_REALM => {} 86 ATTR_SOFTWARE => {} 87 ATTR_NONCE => {} 88 _ => return Err(Error::Other(format!("Unsupported AttrType {attr}"))), 89 }; 90 91 let a = m.get(attr)?; 92 let text = String::from_utf8(a)?; 93 Ok(TextAttribute { attr, text }) 94 } 95 } 96