rusty_copp/messages/
user_data.rs1use der_parser::{
2 Oid,
3 asn1_rs::{Any, FromBer},
4 ber::{BerObject, parse_ber_any},
5 der::{Class, Header, Tag},
6 error::BerError,
7};
8
9use crate::messages::parsers::process_constructed_data;
10
11#[derive(PartialEq, Eq, Clone, Debug)]
12pub enum UserData {
13 FullyEncoded(Vec<PresentationDataValueList>),
14 }
17
18#[derive(PartialEq, Eq, Clone, Debug)]
20pub struct PresentationDataValueList {
21 pub transfer_syntax_name: Option<Oid<'static>>,
22 pub presentation_context_identifier: Vec<u8>,
23 pub presentation_data_values: PresentationDataValues,
24}
25
26#[derive(PartialEq, Eq, Clone, Debug)]
27pub enum PresentationDataValues {
28 SingleAsn1Type(Vec<u8>),
29 }
33
34impl UserData {
35 pub fn to_ber(&self) -> BerObject<'_> {
36 match &self {
37 UserData::FullyEncoded(presentation_data_value_lists) => {
38 let mut pdv_lists = vec![];
39 for presentation_data_value_list in presentation_data_value_lists {
40 pdv_lists.push(presentation_data_value_list.to_ber());
41 }
42 der_parser::ber::BerObject::from_header_and_content(
43 Header::new(Class::Application, true, Tag::from(1), der_parser::ber::Length::Definite(0)),
44 der_parser::ber::BerObjectContent::Sequence(pdv_lists),
45 )
46 }
47 }
48 }
49
50 pub fn parse(data: Any<'_>) -> Result<UserData, BerError> {
51 match data.header.raw_tag() {
52 Some(&[97]) => {
53 let mut presentation_list = vec![];
54 for pdv_list in process_constructed_data(data.data)? {
55 pdv_list.header.assert_class(Class::Universal)?;
56 pdv_list.header.assert_tag(Tag::Sequence)?;
57
58 let mut transfer_syntax_name: Option<Oid<'static>> = None;
59 let mut presentation_contaxt_id = None;
60 let mut presentation_data_values = None;
61 for pdv_list_part in process_constructed_data(pdv_list.data)? {
62 match pdv_list_part.header.raw_tag() {
63 Some(&[6]) => transfer_syntax_name = Some(Oid::from_ber(pdv_list.data)?.1.to_owned()),
64 Some(&[2]) => presentation_contaxt_id = Some(pdv_list_part.data.to_vec()),
65 Some(&[160]) => presentation_data_values = Some(PresentationDataValues::SingleAsn1Type(pdv_list_part.data.to_vec())),
66 x => tracing::warn!("Unknown data in copp user data: {:?}", x),
68 }
69 }
70 presentation_list.push(PresentationDataValueList {
71 transfer_syntax_name,
72 presentation_context_identifier: presentation_contaxt_id.ok_or_else(|| BerError::BerValueError)?,
73 presentation_data_values: presentation_data_values.ok_or_else(|| BerError::BerValueError)?,
74 });
75 }
76 Ok(UserData::FullyEncoded(presentation_list))
77 }
78 _ => todo!(),
79 }
80 }
81
82 pub fn parse_raw(data: &[u8]) -> Result<UserData, BerError> {
83 let (_, packet) = parse_ber_any(data)?;
84 Ok(UserData::parse(packet)?)
85 }
86}
87
88impl PresentationDataValueList {
89 pub fn to_ber(&self) -> BerObject<'_> {
90 let mut object_content = vec![];
91 if let Some(transfer_syntax_name) = &self.transfer_syntax_name {
92 object_content.push(der_parser::ber::BerObject::from_obj(der_parser::ber::BerObjectContent::OID(transfer_syntax_name.clone())));
93 }
94 object_content.push(der_parser::ber::BerObject::from_obj(der_parser::ber::BerObjectContent::Integer(&self.presentation_context_identifier)));
95 object_content.push(self.presentation_data_values.to_ber());
96
97 der_parser::ber::BerObject::from_seq(object_content)
98 }
99}
100
101impl PresentationDataValues {
102 pub fn to_ber(&self) -> BerObject<'_> {
103 match &self {
104 PresentationDataValues::SingleAsn1Type(data) => der_parser::ber::BerObject::from_header_and_content(
105 Header::new(Class::ContextSpecific, true, Tag::from(0), der_parser::ber::Length::Definite(0)),
106 der_parser::ber::BerObjectContent::OctetString(data),
108 ),
109 }
119 }
120}