rustbus/wire/
unmarshal.rs

1//! All things relevant to unmarshalling content from raw bytes
2//!
3//! * `base` and `container` are for the Param approach that map dbus concepts to enums/structs
4//! * `traits` is for the trait based approach
5//! * `iter` is an experimental approach to an libdbus-like iterator
6
7use crate::message_builder::DynamicHeader;
8use crate::message_builder::MarshalledMessage;
9use crate::message_builder::MarshalledMessageBody;
10use crate::message_builder::MessageType;
11use crate::params;
12use crate::signature;
13use crate::wire::errors::UnmarshalError;
14use crate::wire::util::*;
15use crate::wire::HeaderField;
16use crate::ByteOrder;
17
18mod param;
19pub use param::base;
20pub use param::container;
21pub mod iter;
22pub mod traits;
23
24use container::*;
25
26#[derive(Debug, Clone, Copy)]
27pub struct Header {
28    pub byteorder: ByteOrder,
29    pub typ: MessageType,
30    pub flags: u8,
31    pub version: u8,
32    pub body_len: u32,
33    pub serial: u32,
34}
35
36pub struct UnmarshalContext<'fds, 'buf> {
37    pub fds: &'fds [crate::wire::UnixFd],
38    pub buf: &'buf [u8],
39    pub byteorder: ByteOrder,
40    pub offset: usize,
41}
42
43impl UnmarshalContext<'_, '_> {
44    pub fn align_to(&mut self, alignment: usize) -> Result<usize, UnmarshalError> {
45        let padding = crate::wire::util::align_offset(alignment, self.buf, self.offset)?;
46
47        if self.offset + padding > self.buf.len() {
48            Err(UnmarshalError::NotEnoughBytes)
49        } else {
50            self.offset += padding;
51            Ok(padding)
52        }
53    }
54}
55
56impl From<crate::params::validation::Error> for UnmarshalError {
57    fn from(e: crate::params::validation::Error) -> Self {
58        UnmarshalError::Validation(e)
59    }
60}
61impl From<crate::signature::Error> for UnmarshalError {
62    fn from(e: crate::signature::Error) -> Self {
63        UnmarshalError::Validation(crate::params::validation::Error::InvalidSignature(e))
64    }
65}
66
67impl UnmarshalError {
68    /// Checks if `self` is an `EndOfMessage` error.
69    #[inline]
70    pub fn is_end_of_message(&self) -> bool {
71        self == &UnmarshalError::EndOfMessage
72    }
73}
74
75pub const HEADER_LEN: usize = 12;
76
77pub type UnmarshalResult<T> = std::result::Result<(usize, T), UnmarshalError>;
78
79pub fn unmarshal_header(buf: &[u8], offset: usize) -> UnmarshalResult<Header> {
80    if buf.len() < offset + HEADER_LEN {
81        return Err(UnmarshalError::NotEnoughBytes);
82    }
83    let header_slice = &buf[offset..offset + HEADER_LEN];
84
85    let byteorder = match header_slice[0] {
86        b'l' => ByteOrder::LittleEndian,
87        b'B' => ByteOrder::BigEndian,
88        _ => return Err(UnmarshalError::InvalidByteOrder),
89    };
90
91    let typ = match header_slice[1] {
92        1 => MessageType::Call,
93        2 => MessageType::Reply,
94        3 => MessageType::Error,
95        4 => MessageType::Signal,
96        _ => return Err(UnmarshalError::InvalidMessageType),
97    };
98    let flags = header_slice[2];
99    let version = header_slice[3];
100    let (_, body_len) = parse_u32(&header_slice[4..8], byteorder)?;
101    let (_, serial) = parse_u32(&header_slice[8..12], byteorder)?;
102
103    Ok((
104        HEADER_LEN,
105        Header {
106            byteorder,
107            typ,
108            flags,
109            version,
110            body_len,
111            serial,
112        },
113    ))
114}
115
116pub fn unmarshal_dynamic_header(
117    header: &Header,
118    buf: &[u8],
119    offset: usize,
120) -> UnmarshalResult<DynamicHeader> {
121    let (fields_bytes_used, fields) = unmarshal_header_fields(header, buf, offset)?;
122    let mut hdr = DynamicHeader {
123        serial: Some(header.serial),
124        ..Default::default()
125    };
126    collect_header_fields(&fields, &mut hdr);
127    Ok((fields_bytes_used, hdr))
128}
129
130pub fn unmarshal_body<'a, 'e>(
131    byteorder: ByteOrder,
132    sigs: &[crate::signature::Type],
133    buf: &[u8],
134    fds: &[crate::wire::UnixFd],
135    offset: usize,
136) -> UnmarshalResult<Vec<params::Param<'a, 'e>>> {
137    let mut params = Vec::new();
138    let mut body_bytes_used = 0;
139    let mut ctx = UnmarshalContext {
140        fds,
141        buf,
142        byteorder,
143        offset,
144    };
145    for param_sig in sigs {
146        let (bytes, new_param) = unmarshal_with_sig(param_sig, &mut ctx)?;
147        params.push(new_param);
148        body_bytes_used += bytes;
149    }
150    Ok((body_bytes_used, params))
151}
152
153pub fn unmarshal_next_message(
154    header: &Header,
155    dynheader: DynamicHeader,
156    buf: &[u8],
157    offset: usize,
158) -> UnmarshalResult<MarshalledMessage> {
159    let sig = dynheader.signature.clone().unwrap_or_else(|| "".to_owned());
160    let padding = align_offset(8, buf, offset)?;
161
162    if header.body_len == 0 {
163        let msg = MarshalledMessage {
164            dynheader,
165            body: MarshalledMessageBody::from_parts(vec![], vec![], sig, header.byteorder),
166            typ: header.typ,
167            flags: header.flags,
168        };
169        Ok((padding, msg))
170    } else {
171        let offset = offset + padding;
172
173        if buf[offset..].len() < (header.body_len as usize) {
174            return Err(UnmarshalError::NotEnoughBytes);
175        }
176
177        let msg = MarshalledMessage {
178            dynheader,
179            body: MarshalledMessageBody::from_parts(
180                buf[offset..].to_vec(),
181                vec![],
182                sig,
183                header.byteorder,
184            ),
185            typ: header.typ,
186            flags: header.flags,
187        };
188        Ok((padding + header.body_len as usize, msg))
189    }
190}
191
192fn unmarshal_header_fields(
193    header: &Header,
194    buf: &[u8],
195    offset: usize,
196) -> UnmarshalResult<Vec<HeaderField>> {
197    let (_, header_fields_bytes) = parse_u32(&buf[offset..], header.byteorder)?;
198    let offset = offset + 4;
199
200    if offset + header_fields_bytes as usize > buf.len() {
201        return Err(UnmarshalError::NotEnoughBytes);
202    }
203
204    let mut fields = Vec::new();
205    let mut bytes_used_counter = 0;
206
207    while bytes_used_counter < header_fields_bytes as usize {
208        match unmarshal_header_field(header, buf, offset + bytes_used_counter) {
209            Ok((bytes_used, field)) => {
210                fields.push(field);
211                bytes_used_counter += bytes_used;
212            }
213            Err(UnmarshalError::UnknownHeaderField) => {
214                // for the unknown header field code which is always one byte
215                bytes_used_counter += 1;
216
217                // try to validate that there is indeed a valid dbus variant. This is mandatory so the message follows the spec,
218                // even if we just ignore the contents.
219                match crate::wire::validate_raw::validate_marshalled(
220                    header.byteorder,
221                    offset + bytes_used_counter,
222                    buf,
223                    &crate::signature::Type::Container(crate::signature::Container::Variant),
224                ) {
225                    Ok(bytes) => {
226                        // ignore happy path, but increase counter.
227                        bytes_used_counter += bytes;
228                    }
229                    // if the unknown header contains invalid values this is still an error, and the message should be treated as unreadable
230                    Err((_bytes, err)) => return Err(err),
231                }
232            }
233            Err(e) => return Err(e),
234        }
235    }
236    params::validate_header_fields(header.typ, &fields)
237        .map_err(|_| UnmarshalError::InvalidHeaderFields)?;
238
239    Ok((header_fields_bytes as usize + 4, fields))
240}
241
242fn unmarshal_header_field(
243    header: &Header,
244    buf: &[u8],
245    offset: usize,
246) -> UnmarshalResult<HeaderField> {
247    // align to 8 because the header fields are an array structs `a(yv)`
248    let padding = align_offset(8, buf, offset)?;
249    let offset = offset + padding;
250
251    // check that there is enough bytes in the buffer after padding
252    if buf.len() <= offset {
253        return Err(UnmarshalError::NotEnoughBytes);
254    }
255    let typ = buf[offset];
256    let typ_bytes_used = 1;
257    let offset = offset + typ_bytes_used;
258
259    let (sig_bytes_used, sig_str) = unmarshal_signature(&buf[offset..])?;
260    let mut sig =
261        signature::Type::parse_description(sig_str).map_err(|_| UnmarshalError::NoSignature)?;
262    let offset = offset + sig_bytes_used;
263
264    if sig.len() != 1 {
265        // There must be exactly one type in the signature!
266        return Err(UnmarshalError::NoSignature);
267    }
268    let sig = sig.remove(0);
269    let (field_bytes_used, field) = match typ {
270        1 => match sig {
271            signature::Type::Base(signature::Base::ObjectPath) => {
272                let (b, objpath) = unmarshal_string(header.byteorder, &buf[offset..])?;
273                crate::params::validate_object_path(&objpath)?;
274                (b, Ok(HeaderField::Path(objpath)))
275            }
276            _ => (0, Err(UnmarshalError::WrongSignature)),
277        },
278        2 => match sig {
279            signature::Type::Base(signature::Base::String) => {
280                let (b, int) = unmarshal_string(header.byteorder, &buf[offset..])?;
281                (b, Ok(HeaderField::Interface(int)))
282            }
283            _ => (0, Err(UnmarshalError::WrongSignature)),
284        },
285        3 => match sig {
286            signature::Type::Base(signature::Base::String) => {
287                let (b, mem) = unmarshal_string(header.byteorder, &buf[offset..])?;
288                (b, Ok(HeaderField::Member(mem)))
289            }
290            _ => (0, Err(UnmarshalError::WrongSignature)),
291        },
292        4 => match sig {
293            signature::Type::Base(signature::Base::String) => {
294                let (b, name) = unmarshal_string(header.byteorder, &buf[offset..])?;
295                (b, Ok(HeaderField::ErrorName(name)))
296            }
297            _ => (0, Err(UnmarshalError::WrongSignature)),
298        },
299        5 => match sig {
300            signature::Type::Base(signature::Base::Uint32) => {
301                let (b, serial) = parse_u32(&buf[offset..], header.byteorder)?;
302                (b, Ok(HeaderField::ReplySerial(serial)))
303            }
304            _ => (0, Err(UnmarshalError::WrongSignature)),
305        },
306        6 => match sig {
307            signature::Type::Base(signature::Base::String) => {
308                let (b, dest) = unmarshal_string(header.byteorder, &buf[offset..])?;
309                (b, Ok(HeaderField::Destination(dest)))
310            }
311            _ => (0, Err(UnmarshalError::WrongSignature)),
312        },
313        7 => match sig {
314            signature::Type::Base(signature::Base::String) => {
315                let (b, snd) = unmarshal_string(header.byteorder, &buf[offset..])?;
316                (b, Ok(HeaderField::Sender(snd)))
317            }
318            _ => (0, Err(UnmarshalError::WrongSignature)),
319        },
320        8 => match sig {
321            signature::Type::Base(signature::Base::Signature) => {
322                let (b, sig) = unmarshal_signature(&buf[offset..])?;
323                // empty signature is allowed here
324                if !sig.is_empty() {
325                    crate::params::validate_signature(sig)?;
326                }
327                (b, Ok(HeaderField::Signature(sig.to_owned())))
328            }
329            _ => (0, Err(UnmarshalError::WrongSignature)),
330        },
331        9 => match sig {
332            signature::Type::Base(signature::Base::Uint32) => {
333                let (b, fds) = parse_u32(&buf[offset..], header.byteorder)?;
334                (b, Ok(HeaderField::UnixFds(fds)))
335            }
336            _ => (0, Err(UnmarshalError::WrongSignature)),
337        },
338        0 => (0, Err(UnmarshalError::InvalidHeaderField)),
339        _ => (0, Err(UnmarshalError::UnknownHeaderField)),
340    };
341    let sum_bytes_used = padding + typ_bytes_used + sig_bytes_used + field_bytes_used;
342    match field {
343        Ok(field) => Ok((sum_bytes_used, field)),
344        Err(e) => Err(e),
345    }
346}
347
348fn collect_header_fields(header_fields: &[HeaderField], hdr: &mut DynamicHeader) {
349    for h in header_fields {
350        match h {
351            HeaderField::Destination(d) => hdr.destination = Some(d.clone()),
352            HeaderField::ErrorName(e) => hdr.error_name = Some(e.clone()),
353            HeaderField::Interface(s) => hdr.interface = Some(s.clone()),
354            HeaderField::Member(m) => hdr.member = Some(m.clone()),
355            HeaderField::Path(p) => hdr.object = Some(p.clone()),
356            HeaderField::ReplySerial(r) => hdr.response_serial = Some(*r),
357            HeaderField::Sender(s) => hdr.sender = Some(s.clone()),
358            HeaderField::Signature(s) => hdr.signature = Some(s.clone()),
359            HeaderField::UnixFds(u) => hdr.num_fds = Some(*u),
360        }
361    }
362}