Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions ssh-encoding/src/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use alloc::{string::String, vec::Vec};
use bytes::Bytes;

/// Maximum size of a `usize` this library will accept.
const MAX_SIZE: usize = 0xFFFFF;
const MAX_USIZE: usize = 0xFFFFF;

/// Decoding trait.
///
Expand Down Expand Up @@ -102,7 +102,7 @@ impl Decode for usize {
fn decode(reader: &mut impl Reader) -> Result<Self> {
let n = usize::try_from(u32::decode(reader)?)?;

if n <= MAX_SIZE {
if n <= MAX_USIZE {
Ok(n)
} else {
Err(Error::Overflow)
Expand Down Expand Up @@ -162,6 +162,24 @@ impl Decode for String {
}
}

/// Decodes `Vec<String>` from `name-list` as described in [RFC4251 § 5]:
///
/// > A string containing a comma-separated list of names. A name-list
/// > is represented as a uint32 containing its length (number of bytes
/// > that follow) followed by a comma-separated list of zero or more
/// > names. A name MUST have a non-zero length, and it MUST NOT
/// > contain a comma (","). As this is a list of names, all of the
/// > elements contained are names and MUST be in US-ASCII. Context may
/// > impose additional restrictions on the names. For example, the
/// > names in a name-list may have to be a list of valid algorithm
/// > identifiers (see Section 6 below), or a list of [RFC3066] language
/// > tags. The order of the names in a name-list may or may not be
/// > significant. Again, this depends on the context in which the list
/// > is used. Terminating null characters MUST NOT be used, neither
/// > for the individual names, nor for the list as a whole.
///
/// [RFC3066]: https://datatracker.ietf.org/doc/html/rfc3066
/// [RFC4251 § 5]: https://datatracker.ietf.org/doc/html/rfc4251#section-5
#[cfg(feature = "alloc")]
impl Decode for Vec<String> {
type Error = Error;
Expand Down
73 changes: 39 additions & 34 deletions ssh-encoding/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@

//! ## Conventions used in this crate
//!
//! This crate uses the following type labels which are described in
//! [RFC4251 § 5]:
//! This crate uses the following type labels which are described in [RFC4251 § 5], and also lists
//! types with [`Decode`]/[`Encode`] trait impls which are compatible with this format:
//!
//! #### `byte`, `byte[n]`, `byte[]`
//!
//! A byte represents an arbitrary 8-bit value (octet).
//! ### `byte`, `byte[n]`, `byte[]`: arbitrary 8-bit value (octet) or sequence thereof
//! #### [`Decode`]/[`Encode`] trait impls:
//! - `byte`: `u8`
//! - `byte[n]`: `[u8; N]`
//! - `byte[]`: `Vec<u8>`, `bytes::Bytes` (requires `bytes` crate feature)
//!
//! Fixed length data is sometimes represented as an array of bytes, written
//! `byte[n]` where `n` is the number of bytes in the array.
Expand All @@ -37,52 +39,52 @@
//! length bytestrings (similar to `string`, see below) but identifies data
//! which is inherently binary in nature, as opposed to text.
//!
//! #### `boolean`
//!
//! A boolean value is stored as a single byte.
//!
//! ### `boolean`: boolean value stored as a single byte
//! #### [`Decode`]/[`Encode`] trait impls: `bool`
//!
//! The value 0 represents FALSE, and the value 1 represents TRUE. All non-zero
//! values MUST be interpreted as TRUE; however, applications MUST NOT
//! store values other than 0 and 1.
//!
//! #### `uint32`
//!
//! Represents a 32-bit unsigned integer.
//!
//! ### `uint32`: 32-bit unsigned integer
//! #### [`Decode`]/[`Encode`] trait impls: `u32`, `usize`
//!
//! Stored as four bytes in the order of decreasing significance (network byte order).
//!
//! For example: the value `699921578` (`0x29b7f4aa`) is stored as
//! `29 b7 f4 aa`.
//!
//! #### `uint64`
//!
//! Represents a 64-bit unsigned integer.
//! ### `uint64`: 64-bit unsigned integer
//! #### [`Decode`]/[`Encode`] trait impls: `u64`
//!
//! Stored as eight bytes in the order of decreasing significance (network byte order).
//!
//! #### `string`
//! ### `string`: arbitrary length *binary* string
//! #### [`Decode`]/[`Encode`] trait impls: `Vec<u8>`, `String`, `bytes::Bytes` (requires `bytes` crate feature)
//!
//! Arbitrary length binary string.
//! *NOTE: `string` is effectively equivalent to `byte[]`, however the latter is not defined in
//! [RFC4251] and so trait impls in this crate for bytestring types like `[u8; N]` and `Vec<u8>`
//! are described as being impls of `string`*.
//!
//! Strings are allowed to contain arbitrary binary data, including null characters and 8-bit
//! characters.
//!
//! They are stored as a `uint32` containing its length
//! (number of bytes that follow) and zero (= empty string) or more
//! bytes that are the value of the string. Terminating null
//! They are stored as a `uint32` containing its length (number of bytes that follow) and
//! zero (= empty string) or more bytes that are the value of the string. Terminating null
//! characters are not used.
//!
//! Strings are also used to store text. In that case, US-ASCII is
//! used for internal names, and ISO-10646 UTF-8 for text that might
//! be displayed to the user. The terminating null character SHOULD
//! NOT normally be stored in the string. For example: the US-ASCII
//! string "testing" is represented as `00 00 00 07 t e s t i n g`. The
//! UTF-8 mapping does not alter the encoding of US-ASCII characters.
//! Strings are also used to store text. In that case, US-ASCII is used for internal names, and
//! ISO-10646 UTF-8 for text that might be displayed to the user.
//!
//! The terminating null character SHOULD NOT normally be stored in the string.
//!
//! #### `mpint`
//! For example: the US-ASCII string "testing" is represented as `00 00 00 07 t e s t i n g`.
//! The UTF-8 mapping does not alter the encoding of US-ASCII characters.
//!
//! Represents multiple precision integers in two's complement format,
//! stored as a string, 8 bits per byte, MSB first.
//! ### `mpint`: multiple precision integers in two's complement format
//!
//! Stored as a byte string, 8 bits per byte, MSB first (a.k.a. big endian).
//!
//! Negative numbers have the value 1 as the most significant bit of the first byte of
//! the data partition. If the most significant bit would be set for
Expand All @@ -94,7 +96,7 @@
//! By convention, a number that is used in modular computations in
//! `Z_n` SHOULD be represented in the range `0 <= x < n`.
//!
//! Examples:
//! #### Examples:
//!
//! value (hex) | representation (hex)
//! -------------------|---------------------
Expand All @@ -104,9 +106,8 @@
//! `-1234` | `00 00 00 02 ed cc`
//! `-deadbeef` | `00 00 00 05 ff 21 52 41 11`
//!
//! #### `name-list`
//!
//! A string containing a comma-separated list of names.
//! ### `name-list`: string containing a comma-separated list of names
//! #### [`Decode`]/[`Encode`] trait impls: `Vec<String>`
//!
//! A `name-list` is represented as a `uint32` containing its length
//! (number of bytes that follow) followed by a comma-separated list of zero or more
Expand All @@ -125,7 +126,7 @@
//! Terminating null characters MUST NOT be used, neither
//! for the individual names, nor for the list as a whole.
//!
//! Examples:
//! #### Examples:
//!
//! value | representation (hex)
//! ---------------------------|---------------------
Expand All @@ -134,6 +135,7 @@
//! `("zlib,none")` | `00 00 00 09 7a 6c 69 62 2c 6e 6f 6e 65`
//!
//! [RFC3066]: https://datatracker.ietf.org/doc/html/rfc3066
//! [RFC4251]: https://datatracker.ietf.org/doc/html/rfc4251
//! [RFC4251 § 5]: https://datatracker.ietf.org/doc/html/rfc4251#section-5
//!
//! ## Deriving [`Decode`] and [`Encode`]
Expand Down Expand Up @@ -247,3 +249,6 @@ pub use crate::pem::{DecodePem, EncodePem};

#[cfg(feature = "derive")]
pub use ssh_derive::{Decode, Encode};

#[cfg(all(doc, feature = "alloc"))]
use alloc::vec::Vec;